diff --git a/ostd/memory.hh b/ostd/memory.hh index 2c2e987..b8a59be 100644 --- a/ostd/memory.hh +++ b/ostd/memory.hh @@ -1149,6 +1149,21 @@ template constexpr int UsesAllocatorConstructor = detail::UsesAllocCtor::value; +/* util for other classes */ + +namespace detail { + template + class AllocatorDestructor { + A &p_alloc; + Size p_size; + public: + AllocatorDestructor(A &a, Size s) noexcept: p_alloc(a), p_size(s) {} + void operator()(AllocatorPointer p) noexcept { + allocator_deallocate(p_alloc, p, p_size); + } + }; +} + } /* namespace ostd */ #endif diff --git a/ostd/type_traits.hh b/ostd/type_traits.hh index c806f0b..3bfb90e 100644 --- a/ostd/type_traits.hh +++ b/ostd/type_traits.hh @@ -1,6 +1,7 @@ /* Type traits 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_TYPE_TRAITS_HH @@ -294,6 +295,216 @@ namespace detail { template constexpr bool IsMemberFunctionPointer = detail::IsMemberFunctionPointerBase>; +/* internal member traits, from libc++ */ + +namespace detail { + template + struct MemberPointerTraitsBase {}; + + template + struct MemberPointerTraitsBase { + using Class = C; + using Result = R; + using Func = R(A...); + }; + + template + struct MemberPointerTraitsBase { + using Class = C; + using Result = R; + using Func = R(A..., ...); + }; + + template + struct MemberPointerTraitsBase { + using Class = C const; + using Result = R; + using Func = R(A...); + }; + + template + struct MemberPointerTraitsBase { + using Class = C const; + using Result = R; + using Func = R(A..., ...); + }; + + template + struct MemberPointerTraitsBase { + using Class = C volatile; + using Result = R; + using Func = R(A...); + }; + + template + struct MemberPointerTraitsBase { + using Class = C volatile; + using Result = R; + using Func = R(A..., ...); + }; + + template + struct MemberPointerTraitsBase { + using Class = C const volatile; + using Result = R; + using Func = R(A...); + }; + + template + struct MemberPointerTraitsBase< + R (C::*)(A..., ...) const volatile, true, false + > { + using Class = C const volatile; + using Result = R; + using Func = R(A..., ...); + }; + + template + struct MemberPointerTraitsBase { + using Class = C &; + using Result = R; + using Func = R(A...); + }; + + template + struct MemberPointerTraitsBase { + using Class = C &; + using Result = R; + using Func = R(A..., ...); + }; + + template + struct MemberPointerTraitsBase { + using Class = C const &; + using Result = R; + using Func = R(A...); + }; + + template + struct MemberPointerTraitsBase { + using Class = C const &; + using Result = R; + using Func = R(A..., ...); + }; + + template + struct MemberPointerTraitsBase { + using Class = C volatile &; + using Result = R; + using Func = R(A...); + }; + + template + struct MemberPointerTraitsBase< + R (C::*)(A..., ...) volatile &, true, false + > { + using Class = C volatile &; + using Result = R; + using Func = R(A..., ...); + }; + + template + struct MemberPointerTraitsBase< + R (C::*)(A...) const volatile &, true, false + > { + using Class = C const volatile &; + using Result = R; + using Func = R(A...); + }; + + template + struct MemberPointerTraitsBase< + R (C::*)(A..., ...) const volatile &, true, false + > { + using Class = C const volatile &; + using Result = R; + using Func = R(A..., ...); + }; + + template + struct MemberPointerTraitsBase { + using Class = C &&; + using Result = R; + using Func = R(A...); + }; + + template + struct MemberPointerTraitsBase { + using Class = C &&; + using Result = R; + using Func = R(A..., ...); + }; + + template + struct MemberPointerTraitsBase { + using Class = C const &&; + using Result = R; + using Func = R(A...); + }; + + template + struct MemberPointerTraitsBase { + using Class = C const &&; + using Result = R; + using Func = R(A..., ...); + }; + + template + struct MemberPointerTraitsBase { + using Class = C volatile &&; + using Result = R; + using Func = R(A...); + }; + + template + struct MemberPointerTraitsBase< + R (C::*)(A..., ...) volatile &&, true, false + > { + using Class = C volatile &&; + using Result = R; + using Func = R(A..., ...); + }; + + template + struct MemberPointerTraitsBase< + R (C::*)(A...) const volatile &&, true, false + > { + using Class = C const volatile &&; + using Result = R; + using Func = R(A...); + }; + + template + struct MemberPointerTraitsBase< + R (C::*)(A..., ...) const volatile &&, true, false + > { + using Class = C const volatile &&; + using Result = R; + using Func = R(A..., ...); + }; + + template + struct MemberPointerTraitsBase { + using Class = C; + using Result = R; + }; + + template + using MemberPointerClass = typename MemberPointerTraitsBase< + RemoveCv, IsMemberFunctionPointer, IsMemberObjectPointer + >::Class; + + template + using MemberPointerResult = typename MemberPointerTraitsBase< + RemoveCv, IsMemberFunctionPointer, IsMemberObjectPointer + >::Result; + + template + using MemberPointerFunc = typename MemberPointerTraitsBase< + RemoveCv, IsMemberFunctionPointer, IsMemberObjectPointer + >::Func; +} /* namespace detail */ + /* is object */ template @@ -1214,59 +1425,6 @@ namespace detail { template using Conditional = typename detail::ConditionalBase<_cond, T, U>::Type; -/* result of call at compile time */ - -namespace detail { -#define OSTD_FWD(T, _v) static_cast(_v) - template - inline auto rof_invoke(F &&f, A &&...args) -> - decltype(OSTD_FWD(F, f)(OSTD_FWD(A, args)...)) - { - return OSTD_FWD(F, f)(OSTD_FWD(A, args)...); - } - template - inline auto rof_invoke(T B::*pmd, D &&ref) -> - decltype(OSTD_FWD(D, ref).*pmd) - { - return OSTD_FWD(D, ref).*pmd; - } - template - inline auto rof_invoke(PMD &&pmd, P &&ptr) -> - decltype((*OSTD_FWD(P, ptr)).*OSTD_FWD(PMD, pmd)) - { - return (*OSTD_FWD(P, ptr)).*OSTD_FWD(PMD, pmd); - } - template - inline auto rof_invoke(T B::*pmf, D &&ref, A &&...args) -> - decltype((OSTD_FWD(D, ref).*pmf)(OSTD_FWD(A, args)...)) - { - return (OSTD_FWD(D, ref).*pmf)(OSTD_FWD(A, args)...); - } - template - inline auto rof_invoke(PMF &&pmf, P &&ptr, A &&...args) -> - decltype(((*OSTD_FWD(P, ptr)).*OSTD_FWD(PMF, pmf))(OSTD_FWD(A, args)...)) - { - return ((*OSTD_FWD(P, ptr)).*OSTD_FWD(PMF, pmf)) - (OSTD_FWD(A, args)...); - } -#undef OSTD_FWD - - template - struct ResultOfCore {}; - template - struct ResultOfCore(), detail::declval_in()...)))> { - using type = decltype(rof_invoke(detail::declval_in(), - detail::declval_in()...)); - }; - - template - struct ResultOfBase: ResultOfCore {}; -} /* namespace detail */ - -template -using ResultOf = typename detail::ResultOfBase::Type; - /* enable if */ namespace detail { @@ -1280,6 +1438,111 @@ namespace detail { template using EnableIf = typename detail::EnableIfBase::Type; +/* result of call at compile time, from libc++ */ + +namespace detail { + struct InvokeNat { + InvokeNat() = delete; + InvokeNat(InvokeNat const &) = delete; + InvokeNat &operator=(InvokeNat const &) = delete; + ~InvokeNat() = delete; + }; + + struct InvokeAny { InvokeAny(...); }; + +#define OSTD_FWD(T, _v) static_cast(_v) + template + auto func_invoke(InvokeAny, A &&...) -> InvokeNat; + + template< + typename F, typename T, typename ...A, + typename = EnableIf< + IsMemberFunctionPointer> && + IsBaseOf< + RemoveReference>>, + RemoveReference + > + > + > + auto func_invoke(F &&f, T &&v, A &&...args) -> + decltype((OSTD_FWD(T, v).*f)(OSTD_FWD(A, args)...)); + + template< + typename F, typename T, typename ...A, + typename = EnableIf< + IsMemberFunctionPointer> && + IsBaseOf< + RemoveReference>>, + RemoveReference + > + > + > + auto func_invoke(F &&f, T &&v, A &&...args) -> + decltype(((*OSTD_FWD(T, v)).*f)(OSTD_FWD(A, args)...)); + + template< + typename F, typename T, + typename = EnableIf< + IsMemberObjectPointer> && + IsBaseOf< + RemoveReference>>, + RemoveReference + > + > + > + auto func_invoke(F &&f, T &&v) -> decltype(OSTD_FWD(T, v).*f); + + template< + typename F, typename T, + typename = EnableIf< + IsMemberObjectPointer> && + IsBaseOf< + RemoveReference>>, + RemoveReference + > + > + > + auto func_invoke(F &&f, T &&v) -> decltype((*OSTD_FWD(T, v)).*f); + + template + auto func_invoke(F &&f, A &&...args) -> + decltype(OSTD_FWD(F, f)(OSTD_FWD(A, args)...)); +#undef OSTD_FWD + + template + struct FuncInvokableBase { + using Type = decltype( + func_invoke(declval_in(), declval_in()...) + ); + static constexpr bool value = !IsSame; + }; + + template + constexpr bool IsInvokable = FuncInvokableBase::value; + + template + struct InvokeOfBase {}; + + template + struct InvokeOfBase { + using Type = typename FuncInvokableBase::Type; + }; + + template + using InvokeOf = typename InvokeOfBase, F, A...>::Type; + + template + struct ResultOfBase {}; + + template + struct ResultOfBase { + using Type = InvokeOf; + }; +} /* namespace detail */ + +template +using ResultOf = typename detail::ResultOfBase::Type; + /* decay */ namespace detail {