EasyLocalpp  3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
FastFunc.hh
Go to the documentation of this file.
1 #ifndef FastFunc_hh
2 #define FastFunc_hh
3 
8 #include <cstring>
9 #include <type_traits>
10 #include <cassert>
11 #include <cstddef>
12 #include <memory>
13 #include <new>
14 #include <utility>
15 
16 namespace EasyLocal
17 {
18  namespace Core {
19 
20  namespace Impl {
21 
22  namespace Internal
23  {
24  class AnyClass;
25  using AnyPtrThis = AnyClass*;
26  using AnyPtrFunc = void(AnyClass::*)();
27  template<typename TReturn = void, typename... TArgs> using AnyPtrFuncT = TReturn(AnyClass::*)(TArgs...);
28  template<typename TReturn = void, typename... TArgs> using AnyPtrStaticFuncT = TReturn(*)(TArgs...);
29 
30  constexpr std::size_t SingleMemFuncPtrSize{sizeof(void(AnyClass::*)())};
31 
32  template<class TOut, class TIn> union HorribleUnion { TOut out; TIn in; };
33  template<class TOut, class TIn> inline TOut horrible_cast(TIn mIn) noexcept { HorribleUnion<TOut, TIn> u; static_assert(sizeof(TIn) == sizeof(u) && sizeof(TIn) == sizeof(TOut), "Cannot use horrible_cast<>"); u.in = mIn; return u.out; }
34  template<class TOut, class TIn> inline TOut unsafe_horrible_cast(TIn mIn) noexcept { HorribleUnion<TOut, TIn> u; u.in = mIn; return u.out; }
35 
36  template<std::size_t TN> struct SimplifyMemFunc
37  {
38  template<class TThis, class TFunc> inline static AnyPtrThis convert(const TThis*, TFunc, AnyPtrFunc&) noexcept
39  {
40  static_assert(TN - 100, "Unsupported member function pointer on this compiler");
41  return 0;
42  }
43  };
45  {
46  template<class TThis, class TFunc> inline static AnyPtrThis convert(const TThis* mThis, TFunc mFunc, AnyPtrFunc& mFuncOut) noexcept
47  {
48  mFuncOut = reinterpret_cast<AnyPtrFunc>(mFunc);
49  return reinterpret_cast<AnyPtrThis>(const_cast<TThis*>(mThis));
50  }
51  };
52 
53  template<typename TReturn, typename... TArgs> struct Closure
54  {
55  private:
56  using PtrFuncT = AnyPtrFuncT<TReturn, TArgs...>;
57  using PtrStaticFuncT = AnyPtrStaticFuncT<TReturn, TArgs...>;
58  AnyPtrThis ptrThis{nullptr};
59  AnyPtrFunc ptrFunction{nullptr};
60 
61  public:
62  template<class TThis, class TFunc> inline void bind(TThis* mThis, TFunc mFunc) noexcept { ptrThis = SimplifyMemFunc<sizeof(mFunc)>::convert(mThis, mFunc, ptrFunction); }
63  template<class TThis, class TInvoker> inline void bind(TThis* mThis, TInvoker mInvoker, PtrStaticFuncT mFunc) noexcept
64  {
65  if(mFunc == nullptr) ptrFunction = nullptr; else bind(mThis, mInvoker);
66  ptrThis = horrible_cast<AnyPtrThis>(mFunc);
67  }
68 
69  inline bool operator==(std::nullptr_t) const noexcept { return ptrThis == nullptr && ptrFunction == nullptr; }
70  inline bool operator==(const Closure& mRhs) const noexcept { return ptrThis == mRhs.ptrThis && ptrFunction == mRhs.ptrFunction; }
71  inline bool operator==(PtrStaticFuncT mPtr) const noexcept { return mPtr == nullptr ? *this == nullptr : mPtr == reinterpret_cast<PtrStaticFuncT>(getStaticFunc()); }
72  inline bool operator!=(std::nullptr_t) const noexcept { return !operator==(nullptr); }
73  inline bool operator!=(const Closure& mRhs) const noexcept { return !operator==(mRhs); }
74  inline bool operator!=(PtrStaticFuncT mPtr) const noexcept { return !operator==(mPtr); }
75  inline bool operator<(const Closure& mRhs) const { return ptrThis != mRhs.ptrThis ? ptrThis < mRhs.ptrThis : std::memcmp(&ptrFunction, &mRhs.ptrFunction, sizeof(ptrFunction)) < 0; }
76  inline bool operator>(const Closure& mRhs) const { return !operator<(mRhs); }
77 
78  inline std::size_t getHash() const noexcept { return reinterpret_cast<std::size_t>(ptrThis) ^ Internal::unsafe_horrible_cast<std::size_t>(ptrFunction); }
79  inline AnyPtrThis getPtrThis() const noexcept { return ptrThis; }
80  inline PtrFuncT getPtrFunction() const noexcept { return reinterpret_cast<PtrFuncT>(ptrFunction); }
81  inline PtrStaticFuncT getStaticFunc() const noexcept { return horrible_cast<PtrStaticFuncT>(this); }
82  };
83 
84  template<typename TReturn, typename... TArgs> class FastFuncImpl
85  {
86  private:
87  using PtrStaticFuncT = AnyPtrStaticFuncT<TReturn, TArgs...>;
88  Closure<TReturn, TArgs...> closure;
89  inline TReturn invokeStaticFunc(TArgs... mArgs) const { return (*(closure.getStaticFunc()))(std::forward<TArgs>(mArgs)...); }
90 
91  protected:
92  template<class TThis, class TFunc> inline void bind(TThis* mThis, TFunc mFunc) noexcept { closure.bind(mThis, mFunc); }
93  template<class TFunc> inline void bind(TFunc mFunc) noexcept { closure.bind(this, &FastFuncImpl::invokeStaticFunc, mFunc); }
94 
95  public:
96  inline FastFuncImpl() noexcept = default;
97  inline FastFuncImpl(std::nullptr_t) noexcept { }
98  inline FastFuncImpl(PtrStaticFuncT mFunc) noexcept { bind(mFunc); }
99  template<typename X, typename Y> inline FastFuncImpl(X* mThis, Y mFunc) noexcept { bind(mThis, mFunc); }
100 
101 
102  inline FastFuncImpl& operator=(PtrStaticFuncT mFunc) noexcept { bind(mFunc); }
103  inline TReturn operator()(TArgs... mArgs) const { return (closure.getPtrThis()->*(closure.getPtrFunction()))(std::forward<TArgs>(mArgs)...); }
104 
105  inline bool operator==(std::nullptr_t) const noexcept { return closure == nullptr; }
106  inline bool operator==(const FastFuncImpl& mImpl) const noexcept { return closure == mImpl.closure; }
107  inline bool operator==(PtrStaticFuncT mFuncPtr) const noexcept { return closure == mFuncPtr; }
108  inline bool operator!=(std::nullptr_t) const noexcept { return !operator==(nullptr); }
109  inline bool operator!=(const FastFuncImpl& mImpl) const noexcept { return !operator==(mImpl); }
110  inline bool operator!=(PtrStaticFuncT mFuncPtr) const noexcept { return !operator==(mFuncPtr); }
111  inline bool operator<(const FastFuncImpl& mImpl) const { return closure < mImpl.closure; }
112  inline bool operator>(const FastFuncImpl& mImpl) const { return !operator<(mImpl); }
113  };
114  }
115 
116  template<typename T> struct MemFuncToFunc;
117  template<typename TReturn, typename TThis, typename... TArgs> struct MemFuncToFunc<TReturn(TThis::*)(TArgs...) const> { using Type = TReturn(*)(TArgs...); };
118 
119 #define ENABLE_IF_CONV_TO_FUN_PTR(x) typename std::enable_if<std::is_constructible<typename MemFuncToFunc<decltype(&std::decay<x>::type::operator())>::Type, x>::value>::type* = nullptr
120 #define ENABLE_IF_NOT_CONV_TO_FUN_PTR(x) typename std::enable_if<!std::is_constructible<typename MemFuncToFunc<decltype(&std::decay<x>::type::operator())>::Type, x>::value>::type* = nullptr
121 #define ENABLE_IF_SAME_TYPE(x, y) typename = typename std::enable_if<!std::is_same<x, typename std::decay<y>::type>{}>::type
122 
123  template<typename T> class FastFunc;
124  template<typename TReturn, typename... TArgs> class FastFunc<TReturn(TArgs...)> : public Internal::FastFuncImpl<TReturn, TArgs...>
125  {
126  private:
127  using BaseType = Internal::FastFuncImpl<TReturn, TArgs...>;
128  std::shared_ptr<void> storage;
129  template<typename T> inline static void funcDeleter(void* mPtr) { static_cast<T*>(mPtr)->~T(); operator delete(mPtr); }
130 
131  public:
132  using BaseType::BaseType;
133 
134  inline FastFunc() noexcept = default;
135 
136  template<typename TFunc, ENABLE_IF_SAME_TYPE(FastFunc, TFunc)> inline FastFunc(TFunc&& mFunc, ENABLE_IF_CONV_TO_FUN_PTR(TFunc))
137  {
138  using FuncType = typename std::decay<TFunc>::type;
139  this->bind(&mFunc, &FuncType::operator());
140  }
141  template<typename TFunc, ENABLE_IF_SAME_TYPE(FastFunc, TFunc)> inline FastFunc(TFunc&& mFunc, ENABLE_IF_NOT_CONV_TO_FUN_PTR(TFunc))
142  : storage(operator new(sizeof(TFunc)), funcDeleter<typename std::decay<TFunc>::type>)
143  {
144  using FuncType = typename std::decay<TFunc>::type;
145  new (storage.get()) FuncType(std::forward<TFunc>(mFunc));
146  this->bind(storage.get(), &FuncType::operator());
147  }
148  };
149 
150 #undef ENABLE_IF_CONV_TO_FUN_PTR
151 #undef ENABLE_IF_NOT_CONV_TO_FUN_PTR
152 #undef ENABLE_IF_SAME_TYPE
153  }
154  }
155 }
156 
157 #endif
FastFuncImpl & operator=(PtrStaticFuncT mFunc) noexcept
Definition: FastFunc.hh:102
bool operator!=(std::nullptr_t) const noexcept
Definition: FastFunc.hh:72
TOut horrible_cast(TIn mIn) noexcept
Definition: FastFunc.hh:33
bool operator!=(PtrStaticFuncT mFuncPtr) const noexcept
Definition: FastFunc.hh:110
bool operator!=(const Closure &mRhs) const noexcept
Definition: FastFunc.hh:73
bool operator==(PtrStaticFuncT mPtr) const noexcept
Definition: FastFunc.hh:71
bool operator!=(const FastFuncImpl &mImpl) const noexcept
Definition: FastFunc.hh:109
static AnyPtrThis convert(const TThis *mThis, TFunc mFunc, AnyPtrFunc &mFuncOut) noexcept
Definition: FastFunc.hh:46
bool operator>(const FastFuncImpl &mImpl) const
Definition: FastFunc.hh:112
static AnyPtrThis convert(const TThis *, TFunc, AnyPtrFunc &) noexcept
Definition: FastFunc.hh:38
AnyPtrThis getPtrThis() const noexcept
Definition: FastFunc.hh:79
bool operator==(std::nullptr_t) const noexcept
Definition: FastFunc.hh:105
TReturn(*)(TArgs...) AnyPtrStaticFuncT
Definition: FastFunc.hh:28
PtrStaticFuncT getStaticFunc() const noexcept
Definition: FastFunc.hh:81
bool operator==(const FastFuncImpl &mImpl) const noexcept
Definition: FastFunc.hh:106
PtrFuncT getPtrFunction() const noexcept
Definition: FastFunc.hh:80
bool operator==(const Closure &mRhs) const noexcept
Definition: FastFunc.hh:70
bool operator<(const Closure &mRhs) const
Definition: FastFunc.hh:75
void bind(TThis *mThis, TInvoker mInvoker, PtrStaticFuncT mFunc) noexcept
Definition: FastFunc.hh:63
void(AnyClass::*)( AnyPtrFunc)
Definition: FastFunc.hh:26
std::size_t getHash() const noexcept
Definition: FastFunc.hh:78
bool operator<(const FastFuncImpl &mImpl) const
Definition: FastFunc.hh:111
bool operator!=(PtrStaticFuncT mPtr) const noexcept
Definition: FastFunc.hh:74
void bind(TThis *mThis, TFunc mFunc) noexcept
Definition: FastFunc.hh:62
#define ENABLE_IF_CONV_TO_FUN_PTR(x)
Definition: FastFunc.hh:119
TReturn operator()(TArgs...mArgs) const
Definition: FastFunc.hh:103
FastFuncImpl(X *mThis, Y mFunc) noexcept
Definition: FastFunc.hh:99
void bind(TThis *mThis, TFunc mFunc) noexcept
Definition: FastFunc.hh:92
TReturn(AnyClass::*)(TArgs...) AnyPtrFuncT
Definition: FastFunc.hh:27
bool operator!=(std::nullptr_t) const noexcept
Definition: FastFunc.hh:108
FastFuncImpl(PtrStaticFuncT mFunc) noexcept
Definition: FastFunc.hh:98
bool operator==(std::nullptr_t) const noexcept
Definition: FastFunc.hh:69
TOut unsafe_horrible_cast(TIn mIn) noexcept
Definition: FastFunc.hh:34
#define ENABLE_IF_NOT_CONV_TO_FUN_PTR(x)
Definition: FastFunc.hh:120
FastFunc(TFunc &&mFunc, ENABLE_IF_NOT_CONV_TO_FUN_PTR(TFunc))
Definition: FastFunc.hh:141
constexpr std::size_t SingleMemFuncPtrSize
Definition: FastFunc.hh:30
FastFunc(TFunc &&mFunc, ENABLE_IF_CONV_TO_FUN_PTR(TFunc))
Definition: FastFunc.hh:136
bool operator==(PtrStaticFuncT mFuncPtr) const noexcept
Definition: FastFunc.hh:107
bool operator>(const Closure &mRhs) const
Definition: FastFunc.hh:76