diff --git a/ostd/event.hh b/ostd/event.hh index 7b96958..336d004 100644 --- a/ostd/event.hh +++ b/ostd/event.hh @@ -19,7 +19,7 @@ namespace detail { SignalBase(SignalBase const &ev): p_class(ev.p_class), p_nfuncs(ev.p_nfuncs) { - using Func = Function; + using Func = std::function; byte *bufp = new byte[sizeof(Func) * p_nfuncs]; Func *nbuf = reinterpret_cast(bufp); for (Size i = 0; i < p_nfuncs; ++i) @@ -34,7 +34,7 @@ namespace detail { } SignalBase &operator=(SignalBase const &ev) { - using Func = Function; + using Func = std::function; p_class = ev.p_class; p_nfuncs = ev.p_nfuncs; byte *bufp = new byte[sizeof(Func) * p_nfuncs]; @@ -54,8 +54,9 @@ namespace detail { ~SignalBase() { clear(); } void clear() { + using func = std::function; for (Size i = 0; i < p_nfuncs; ++i) { - p_funcs[i].~Function(); + p_funcs[i].~func(); } delete[] reinterpret_cast(p_funcs); p_funcs = nullptr; @@ -64,7 +65,7 @@ namespace detail { template Size connect(F &&func) { - using Func = Function; + using Func = std::function; for (Size i = 0; i < p_nfuncs; ++i) { if (!p_funcs[i]) { p_funcs[i] = std::forward(func); @@ -121,7 +122,7 @@ namespace detail { private: C *p_class; - Function *p_funcs; + std::function *p_funcs; Size p_nfuncs; }; } /* namespace detail */ diff --git a/ostd/functional.hh b/ostd/functional.hh index f6ed9bd..79641c3 100644 --- a/ostd/functional.hh +++ b/ostd/functional.hh @@ -1,7 +1,6 @@ /* Function objects for OctaSTD. * * This file is part of OctaSTD. See COPYING.md for futher information. - * Portions of this file are originally adapted from the libc++ project. */ #ifndef OSTD_FUNCTIONAL_HH @@ -440,550 +439,6 @@ typename ToHash::Result to_hash(T const &v) { return ToHash()(v); } -/* mem_fn */ - -namespace detail { - template - struct MemTypes; - template - struct MemTypes { - using Result = R; - using Argument = T; - }; - template - struct MemTypes { - using Result = R; - using FirstArgument = T; - using SecondArgument = A; - }; - template - struct MemTypes { - using Result = R; - using Argument = T const; - }; - template - struct MemTypes { - using Result = R; - using FirstArgument = T const; - using SecondArgument = A; - }; - - template - class MemFn: MemTypes { - R T::*p_ptr; - public: - MemFn(R T::*ptr): p_ptr(ptr) {} - template - auto operator()(T &obj, A &&...args) -> - decltype(((obj).*(p_ptr))(std::forward(args)...)) - { - return ((obj).*(p_ptr))(std::forward(args)...); - } - template - auto operator()(T const &obj, A &&...args) -> - decltype(((obj).*(p_ptr))(std::forward(args)...)) - const { - return ((obj).*(p_ptr))(std::forward(args)...); - } - template - auto operator()(T *obj, A &&...args) -> - decltype(((obj)->*(p_ptr))(std::forward(args)...)) - { - return ((obj)->*(p_ptr))(std::forward(args)...); - } - template - auto operator()(T const *obj, A &&...args) -> - decltype(((obj)->*(p_ptr))(std::forward(args)...)) - const { - return ((obj)->*(p_ptr))(std::forward(args)...); - } - }; -} /* namespace detail */ - -template -detail::MemFn mem_fn(R T:: *ptr) { - return detail::MemFn(ptr); -} - -/* function impl adapted from libc++ - */ - -template -class Function; - -namespace detail { - template - inline bool func_is_not_null(T const &) { - return true; - } - - template - inline bool func_is_not_null(T *ptr) { - return ptr; - } - - template - inline bool func_is_not_null(R C::*ptr) { - return ptr; - } - - template - inline bool func_is_not_null(Function const &f) { - return !!f; - } - - template - struct FuncInvokeVoidReturnWrapper { - template - static R call(A &&...args) { - return func_invoke(std::forward(args)...); - } - }; - - template<> - struct FuncInvokeVoidReturnWrapper { - template - static void call(A &&...args) { - func_invoke(std::forward(args)...); - } - }; - - template - class FuncBase; - - template - class FuncBase { - FuncBase(FuncBase const &); - FuncBase &operator=(FuncBase const &); - public: - FuncBase() {} - virtual ~FuncBase() {} - virtual FuncBase *clone() const = 0; - virtual void clone(FuncBase *) const = 0; - virtual void destroy() noexcept = 0; - virtual void destroy_deallocate() noexcept = 0; - virtual R operator()(A &&...args) = 0; - }; - - template - class FuncCore; - - template - class FuncCore: public FuncBase { - CompressedPair f_stor; -public: - explicit FuncCore(F &&f): - f_stor( - std::piecewise_construct, - std::forward_as_tuple(std::move(f)), - std::forward_as_tuple() - ) - {} - - explicit FuncCore(F const &f, A const &a): - f_stor( - std::piecewise_construct, - std::forward_as_tuple(f), - std::forward_as_tuple(a) - ) - {} - - explicit FuncCore(F const &f, A &&a): - f_stor( - std::piecewise_construct, - std::forward_as_tuple(f), - std::forward_as_tuple(std::move(a)) - ) - {} - - explicit FuncCore(F &&f, A &&a): - f_stor( - std::piecewise_construct, - std::forward_as_tuple(std::move(f)), - std::forward_as_tuple(std::move(a)) - ) - {} - - virtual FuncBase *clone() const; - virtual void clone(FuncBase *) const; - virtual void destroy() noexcept; - virtual void destroy_deallocate() noexcept; - virtual R operator()(AT &&...args); - }; - - template - FuncBase *FuncCore::clone() const { - using AA = AllocatorRebind; - AA a(f_stor.second()); - using D = AllocatorDestructor; - Box hold(a.allocate(1), D(a, 1)); - ::new(hold.get()) FuncCore(f_stor.first(), A(a)); - return hold.release(); - } - - template - void FuncCore::clone(FuncBase *p) const { - ::new (p) FuncCore(f_stor.first(), f_stor.second()); - } - - template - void FuncCore::destroy() noexcept { - f_stor.~CompressedPair(); - } - - template - void FuncCore::destroy_deallocate() noexcept { - using AA = AllocatorRebind; - AA a(f_stor.second()); - f_stor.~CompressedPair(); - a.deallocate(this, 1); - } - - template - R FuncCore::operator()(AT &&...args) { - using Invoker = FuncInvokeVoidReturnWrapper; - return Invoker::call(f_stor.first(), std::forward(args)...); - } -} /* namespace detail */ - -template -class Function { - using Base = detail::FuncBase; - AlignedStorage<3 * sizeof(void *)> p_buf; - Base *p_f; - - static inline Base *as_base(void *p) { - return reinterpret_cast(p); - } - - template< - typename F, - bool = !IsSame && detail::IsInvokable - > - struct CallableBase; - - template - struct CallableBase { - static constexpr bool value = - IsSame || IsConvertible, R>; - }; - template - struct CallableBase { - static constexpr bool value = false; - }; - - template - static constexpr bool Callable = CallableBase::value; - -public: - using Result = R; - - Function() noexcept: p_f(nullptr) {} - Function(Nullptr) noexcept: p_f(nullptr) {} - - Function(Function const &); - Function(Function &&) noexcept; - - template< - typename F, typename = EnableIf && !IsSame> - > - Function(F); - - template - Function(AllocatorArg, A const &) noexcept: p_f(nullptr) {} - template - Function(AllocatorArg, A const &, Nullptr) noexcept: p_f(nullptr) {} - template - Function(AllocatorArg, A const &, Function const &); - template - Function(AllocatorArg, A const &, Function &&); - template>> - Function(AllocatorArg, A const &, F); - - Function &operator=(Function const &f) { - Function(f).swap(*this); - return *this; - } - - Function &operator=(Function &&) noexcept; - Function &operator=(Nullptr) noexcept; - - template - EnableIf< - Callable> && !IsSame, Function>, - Function & - > operator=(F &&f) { - Function(std::forward(f)).swap(*this); - return *this; - } - - ~Function(); - - void swap(Function &) noexcept; - - explicit operator bool() const noexcept { return p_f; } - - /* deleted overloads close possible hole in the type system */ - template - bool operator==(Function &) const = delete; - template - bool operator!=(Function &) const = delete; - - R operator()(Args ...a) const { - return (*p_f)(std::forward(a)...); - } -}; - -template -Function::Function(Function const &f) { - if (!f.p_f) { - p_f = nullptr; - } else if (static_cast(f.p_f) == &f.p_buf) { - p_f = as_base(&p_buf); - f.p_f->clone(p_f); - } else { - p_f = f.p_f->clone(); - } -} - -template -template -Function::Function( - AllocatorArg, A const &, Function const &f -) { - if (!f.p_f) { - p_f = nullptr; - } else if (static_cast(f.p_f) == &f.p_buf) { - p_f = as_base(&p_buf); - f.p_f->clone(p_f); - } else { - p_f = f.p_f->clone(); - } -} - -template -Function::Function(Function &&f) noexcept { - if (!f.p_f) { - p_f = nullptr; - } else if (static_cast(f.p_f) == &f.p_buf) { - p_f = as_base(&p_buf); - f.p_f->clone(p_f); - } else { - p_f = f.p_f; - f.p_f = nullptr; - } -} - -template -template -Function::Function( - AllocatorArg, A const &, Function &&f -) { - if (!f.p_f) { - p_f = nullptr; - } else if (static_cast(f.p_f) == &f.p_buf) { - p_f = as_base(&p_buf); - f.p_f->clone(p_f); - } else { - p_f = f.p_f; - f.p_f = nullptr; - } -} - -template -template -Function::Function(F f): p_f(nullptr) { - if (!detail::func_is_not_null(f)) { - return; - } - using FF = detail::FuncCore, R(Args...)>; - if ((sizeof(FF) <= sizeof(p_buf)) && IsNothrowCopyConstructible) { - p_f = ::new(static_cast(&p_buf)) FF(std::move(f)); - return; - } - using AA = Allocator; - AA a; - using D = detail::AllocatorDestructor; - Box hold(a.allocate(1), D(a, 1)); - ::new(hold.get()) FF(std::move(f), Allocator(a)); - p_f = hold.release(); -} - -template -template -Function::Function(AllocatorArg, A const &a, F f): - p_f(nullptr) -{ - if (!detail::func_is_not_null(f)) { - return; - } - using FF = detail::FuncCore; - using AA = AllocatorRebind; - AA aa(a); - if ( - (sizeof(FF) <= sizeof(p_buf)) && IsNothrowCopyConstructible && - IsNothrowCopyConstructible - ) { - p_f = ::new(static_cast(&p_buf)) FF(std::move(f), A(aa)); - return; - } - using D = detail::AllocatorDestructor; - Box hold(aa.allocate(1), D(aa, 1)); - ::new(hold.get()) FF(std::move(f), A(aa)); - p_f = hold.release(); -} - -template -Function &Function::operator=(Function &&f) - noexcept -{ - if (static_cast(p_f) == &p_buf) { - p_f->destroy(); - } else if (p_f) { - p_f->destroy_deallocate(); - } - if (f.p_f == nullptr) { - p_f = nullptr; - } else if (static_cast(f.p_f) == &f.p_buf) { - p_f = as_base(&p_buf); - f.p_f->clone(p_f); - } else { - p_f = f.p_f; - f.p_f = nullptr; - } - return *this; -} - -template -Function &Function::operator=(Nullptr) noexcept { - if (static_cast(p_f) == &p_buf) { - p_f->destroy(); - } else if (p_f) { - p_f->destroy_deallocate(); - } - p_f = nullptr; - return *this; -} - -template -Function::~Function() { - if (static_cast(p_f) == &p_buf) { - p_f->destroy(); - } else if (p_f) { - p_f->destroy_deallocate(); - } -} - -template -void Function::swap(Function &f) noexcept { - if ( - (static_cast(p_f) == &p_buf) && - (static_cast(f.p_f) == &f.p_buf) - ) { - /* both in small storage */ - AlignedStorage tmpbuf; - Base *t = as_base(&tmpbuf); - p_f->clone(t); - p_f->destroy(); - p_f = nullptr; - f.p_f->clone(as_base(&p_buf)); - f.p_f->destroy(); - f.p_f = nullptr; - p_f = as_base(&p_buf); - t->clone(as_base(&f.p_buf)); - t->destroy(); - f.p_f = as_base(&f.p_buf); - } else if (static_cast(p_f) == &p_buf) { - /* ours in small storage */ - p_f->clone(as_base(&f.p_buf)); - p_f->destroy(); - p_f = f.p_f; - f.p_f = as_base(&f.p_buf); - } else if (static_cast(f.p_f) == &f.p_buf) { - /* the other in small storage */ - f.p_f->clone(as_base(&p_buf)); - f.p_f->destroy(); - f.p_f = p_f; - p_f = as_base(&p_buf); - } else { - detail::swap_adl(p_f, f.p_f); - } -} - -template -inline bool operator==(Function const &f, Nullptr) noexcept { - return !f; -} - -template -inline bool operator==(Nullptr, Function const &f) noexcept { - return !f; -} - -template -inline bool operator!=(Function const &f, Nullptr) noexcept { - return bool(f); -} - -template -inline bool operator!=(Nullptr, Function const &f) noexcept { - return bool(f); -} - -namespace detail { - template - struct DcLambdaTypes: DcLambdaTypes {}; - - template - struct DcLambdaTypes { - using Ptr = R (*)(A...); - using Obj = Function; - }; - - template - static char dc_func_test(typename DcLambdaTypes::Ptr); - template - static int dc_func_test(...); - - template - constexpr bool DcFuncTest = (sizeof(dc_func_test(declval())) == 1); - - template> - struct DcFuncTypeObjBase { - using Type = typename DcLambdaTypes::Obj; - }; - - template - struct DcFuncTypeObjBase { - using Type = typename DcLambdaTypes::Ptr; - }; - - template && IsMoveConstructible - > - struct DcFuncTypeObj { - using Type = typename DcFuncTypeObjBase::Type; - }; - - template - struct DcFuncTypeObj { - using Type = F; - }; - - template> - struct DcFuncType { - using Type = F; - }; - - template - struct DcFuncType { - using Type = typename DcFuncTypeObj::Type; - }; -} - -template -using FunctionMakeDefaultConstructible = typename detail::DcFuncType::Type; - } /* namespace ostd */ #endif diff --git a/ostd/utility.hh b/ostd/utility.hh index d8277b5..c7f8a66 100644 --- a/ostd/utility.hh +++ b/ostd/utility.hh @@ -52,9 +52,9 @@ inline void swap(T &a, T &b) noexcept(noexcept(detail::swap_fb(a, b))) { } template -inline void swap(T (&a)[N], T (&b)[N]) noexcept(noexcept(swap(*a, *b))) { +inline void swap(T (&a)[N], T (&b)[N]) noexcept(noexcept(ostd::swap(*a, *b))) { for (Size i = 0; i < N; ++i) { - swap(a[i], b[i]); + ostd::swap(a[i], b[i]); } } @@ -62,8 +62,8 @@ namespace detail { namespace adl_swap { using ostd::swap; template - inline void swap_adl(T &a, T &b) noexcept(noexcept(swap(a, b))) { - swap(a, b); + inline void swap_adl(T &a, T &b) noexcept(noexcept(ostd::swap(a, b))) { + ostd::swap(a, b); } } template