From f549d876e4be9366c9389d884ecce6691e59824d Mon Sep 17 00:00:00 2001 From: q66 Date: Sat, 18 Apr 2015 16:46:44 +0100 Subject: [PATCH] ResultOf trait, declval --- octa/traits.h | 63 +++++++++++++++++++++++++++++++++++--------------- octa/utility.h | 35 +++++++++++++++++++++++----- 2 files changed, 74 insertions(+), 24 deletions(-) diff --git a/octa/traits.h b/octa/traits.h index edc95b4..2156979 100644 --- a/octa/traits.h +++ b/octa/traits.h @@ -9,6 +9,7 @@ #include #include "octa/types.h" +#include "octa/utility.h" namespace octa { /* conditional */ @@ -25,9 +26,7 @@ namespace octa { /* removers */ - template struct RemoveReference { typedef T type; }; - template struct RemoveReference { typedef T type; }; - template struct RemoveReference { typedef T type; }; + template using RemoveReference = internal::RemoveReference; template struct RemoveConst { typedef T type; }; template struct RemoveConst { typedef T type; }; @@ -180,27 +179,55 @@ namespace octa { /* add rvalue reference */ - template struct AddRvalueReference { typedef T &&type; }; - template struct AddRvalueReference { typedef T &&type; }; - template struct AddRvalueReference { typedef T &&type; }; - template<> struct AddRvalueReference { - typedef void type; - }; - template<> struct AddRvalueReference { - typedef const void type; - }; - template<> struct AddRvalueReference { - typedef volatile void type; - }; - template<> struct AddRvalueReference { - typedef const volatile void type; - }; + template using AddRvalueReference = internal::AddRvalueReference; /* is array */ template struct IsArray : false_t {}; template struct IsArray: true_t {}; template struct IsArray: true_t {}; + + /* result of call at compile time */ + + namespace internal { + template + inline auto result_of_invoke(F &&f, A &&...args) -> + decltype(forward(f)(forward(args)...)) { + return forward(f)(forward(args)...); + } + template + inline auto result_of_invoke(T B::*pmd, D &&ref) -> + decltype(forward(ref).*pmd) { + return forward(ref).*pmd; + } + template + inline auto result_of_invoke(PMD &&pmd, P &&ptr) -> + decltype((*forward

(ptr)).*forward(pmd)) { + return (*forward

(ptr)).*forward(pmd); + } + template + inline auto result_of_invoke(T B::*pmf, D &&ref, A &&...args) -> + decltype((forward(ref).*pmf)(forward(args)...)) { + return (forward(ref).*pmf)(forward(args)...); + } + template + inline auto result_of_invoke(PMF &&pmf, P &&ptr, A &&...args) -> + decltype(((*forward

(ptr)).*forward(pmf))(forward(args)...)) { + return ((*forward

(ptr)).*forward(pmf))(forward(args)...); + } + + template + struct ResultOf {}; + template + struct ResultOf(), declval()...)))> { + using type = decltype(internal::result_of_invoke(declval(), + declval()...)); + }; + } + + /* cppreference.com used for reference */ + template struct ResultOf: internal::ResultOf {}; } #endif \ No newline at end of file diff --git a/octa/utility.h b/octa/utility.h index 6960070..934cf9f 100644 --- a/octa/utility.h +++ b/octa/utility.h @@ -8,8 +8,6 @@ #include -#include "octa/traits.h" - /* must be in std namespace otherwise the compiler won't know about it */ namespace std { template @@ -51,23 +49,48 @@ namespace octa { } } + /* aliased in traits.h later */ + namespace internal { + template struct RemoveReference { typedef T type; }; + template struct RemoveReference { typedef T type; }; + template struct RemoveReference { typedef T type; }; + + template struct AddRvalueReference { typedef T &&type; }; + template struct AddRvalueReference { typedef T &&type; }; + template struct AddRvalueReference { typedef T &&type; }; + template<> struct AddRvalueReference { + typedef void type; + }; + template<> struct AddRvalueReference { + typedef const void type; + }; + template<> struct AddRvalueReference { + typedef volatile void type; + }; + template<> struct AddRvalueReference { + typedef const volatile void type; + }; + } + template - static inline constexpr typename RemoveReference::type && + static inline constexpr typename internal::RemoveReference::type && move(T &&v) noexcept { - return static_cast::type &&>(v); + return static_cast::type &&>(v); } template static inline constexpr T && - forward(typename RemoveReference::type &v) noexcept { + forward(typename internal::RemoveReference::type &v) noexcept { return static_cast(v); } template static inline constexpr T && - forward(typename RemoveReference::type &&v) noexcept { + forward(typename internal::RemoveReference::type &&v) noexcept { return static_cast(v); } + + template typename internal::AddRvalueReference::type declval(); } #endif \ No newline at end of file