TrueReality  v0.1.1912
Functor.h
Go to the documentation of this file.
1 /*
2 * True Reality Open Source Game and Simulation Engine
3 * Copyright © 2021 Acid Rain Studios LLC
4 *
5 * The Base of this class has been adopted from the Delta3D engine
6 *
7 * This library is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU Lesser General Public License as published by the Free
9 * Software Foundation; either version 3.0 of the License, or (at your option)
10 * any later version.
11 *
12 * This library is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15 * details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * @author Maxim Serebrennik
22 */
23 
24 #pragma once
25 
26 #include <trUtil/FunCall.h>
27 #include <trUtil/FunTraits.h>
28 #include <trUtil/TypeList.h>
29 
30 #include <stdlib.h>
31 #include <utility>
32 
38 namespace trUtil
39 {
40  // Generalized functor implementation. Concept inspired by Andrei Alexandrescu.
41  // Copyright Aleksei Trunov 2005
42  // Use, copy, modify, distribute and sell it for free.
43  //
44  // Generalized functor class template
45 
46 
52  template <typename R, class TList, unsigned int size = 4 * sizeof(void*)>
53  class Functor
54  {
55  public:
56  using ResultType = R ;
57  using TypeListType = TList;
59 
65  Functor() : vptr_(0) {}
66 
73  {
74  if (vptr_) vptr_->destroy_(*this);
75  }
76 
84  Functor(Functor const& src)
85  {
86  vptr_ = src.vptr_ ? src.vptr_->clone_(src, *this) : NULL;
87  }
88 
98  Functor& operator=(Functor const& src)
99  {
100  if (this != &src) {
101  if (vptr_) vptr_->destroy_(*this);
102  vptr_ = src.vptr_ ? src.vptr_->clone_(src, *this) : NULL;
103  }
104  return *this;
105  }
106 
114  bool operator!() const { return vptr_ == NULL; }
115 
123  bool valid() const { return vptr_ != NULL; }
124 
133  template <typename F> explicit Functor(F const& fun)
134  {
135  using StoredType = FunctorImpl<F>;
136  vptr_ = _init<StoredType>(fun);
137  }
138 
149  template <class P, typename MF> explicit Functor(P const& pobj, MF memfun)
150  {
151  using StoredType = MemberFnImpl<P, MF>;
152  vptr_ = _init<StoredType>(std::pair<P, MF>(pobj, memfun));
153  }
154  // calls
162 #define DoCall(parms) return vptr_->call_(*this, parms);
163  inline R operator()(ParmsListType const& parms) const { DoCall(parms) }
164  inline R operator()() const { DoCall(CallParms<TList>::Make()) }
165  inline R operator()(Parm1 p1) const { DoCall(CallParms<TList>::Make(p1)) }
166  inline R operator()(Parm1 p1, Parm2 p2) const { DoCall(CallParms<TList>::Make(p1, p2)) }
167  inline R operator()(Parm1 p1, Parm2 p2, Parm3 p3) const { DoCall(CallParms<TList>::Make(p1, p2, p3)) }
168  inline R operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) const { DoCall(CallParms<TList>::Make(p1, p2, p3, p4)) }
169  inline R operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) const { DoCall(CallParms<TList>::Make(p1, p2, p3, p4, p5)) }
170  inline R operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, Parm6 p6) const { DoCall(CallParms<TList>::Make(p1, p2, p3, p4, p5, p6)) }
171  inline R operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, Parm6 p6, Parm7 p7) const { DoCall(CallParms<TList>::Make(p1, p2, p3, p4, p5, p6, p7)) }
172  private:
173  // copying/destruction and calls implementation
174  struct FunImplBase
175  {
176  struct VTable;
177  struct VTable
178  {
179  void(*destroy_)(Functor const&);
180  VTable* (*clone_)(Functor const&, Functor&);
181  R(*call_)(Functor const&, ParmsListType);
182  };
183  // VTable vtbl_; // not needed here and actually wastes space!
184  };
185  template <typename V, class Derived>
186  struct FunStorageImpl : public FunImplBase
187  {
188  V val_;
189  FunStorageImpl(V const& val) : val_(val) {}
190  static void Destroy(Functor const& src) { src.val_.template destroy<Derived>(); }
191  static typename FunImplBase::VTable* Clone(Functor const& src, Functor& dest)
192  {
193  Derived const& this_ = src.val_.template get<Derived const>();
194  return dest._init<Derived>(this_.val_);
195  }
196  };
197  template <typename T>
198  struct FunctorImpl : public FunStorageImpl<T, FunctorImpl<T> >
199  {
200  FunctorImpl(T const& val) : FunStorageImpl<T, FunctorImpl>(val) {}
201  static R Call(Functor const& src, ParmsListType parms)
202  {
203  FunctorImpl const& this_ = src.val_.template get<FunctorImpl const>();
204  return FunctorCall<T, R, TList>::Call(this_.val_, parms);
205  }
206  };
207  template <class P, typename T>
208  struct MemberFnImpl : public FunStorageImpl<std::pair<P, T>, MemberFnImpl<P, T> >
209  {
210  MemberFnImpl(std::pair<P, T> const& val) : FunStorageImpl<std::pair<P, T>, MemberFnImpl>(val) {}
211  static R Call(Functor const& src, ParmsListType parms)
212  {
213  MemberFnImpl const& this_ = src.val_.template get<MemberFnImpl const>();
214  return FunctorCall<T, R, TList>::Call(this_.val_.first, this_.val_.second, parms);
215  }
216  };
217  // initialization helper
218  template <class T, class V>
219  typename FunImplBase::VTable* _init(V const& v)
220  {
221  val_.template init<T>(v);
222  static typename FunImplBase::VTable vtbl =
223  {
224  &T::Destroy,
225  &T::Clone,
226  &T::Call,
227  };
228  return &vtbl;
229  }
230  // typeless storage support
231  struct Typeless
232  {
233  template <typename T> inline T* init1(T* v) { return new(getbuf()) T(v); }
234  template <typename T, typename V> inline T* init(V const& v) { return new(getbuf()) T(v); }
235  template <typename T> inline void destroy() const { (*reinterpret_cast<T const*>(getbuf())).~T(); }
236  template <typename T> inline T const& get() const { return *reinterpret_cast<T const*>(getbuf()); }
237  template <typename T> inline T& get() { return *reinterpret_cast<T*>(getbuf()); }
238  void* getbuf() { return &buffer_[0]; }
239  void const* getbuf() const { return &buffer_[0]; }
240  unsigned char buffer_[size];
241  };
242  template <typename T>
243  struct ByValue
244  {
245  template <typename V> inline static T* init(Typeless& val, V const& v) { return val.template init<T>(v); }
246  inline static void destroy(Typeless const& val) { val.template destroy<T>(); }
247  inline static T const& get(Typeless const& val) { return val.template get<T>(); }
248  inline static T& get(Typeless& val) { return val.template get<T>(); }
249  };
250  template <typename T>
251  struct NewAlloc
252  {
253  template <typename V> inline static T* init(Typeless& val, V const& v) { return *val.template init<T*>(new T(v)); }
254  inline static void destroy(Typeless const& val) { delete val.template get<T*>(); }
255  inline static T const& get(Typeless const& val) { return *val.template get<T const*>(); }
256  inline static T& get(Typeless& val) { return *val.template get<T*>(); }
257  };
258  template <typename T>
260  {
261  // TODO: it seems this is a good place to add alignment calculations
263  };
264  struct Stored
265  {
266  template <typename T, typename V> inline T* init(V const& v) { return SelectStored<T>::Type::init(val_, v); }
267  template <typename T> inline void destroy() const { SelectStored<T>::Type::destroy(val_); }
268  template <typename T> inline T const& get() const { return SelectStored<T>::Type::get(val_); }
269  template <typename T> inline T& get() { return SelectStored<T>::Type::get(val_); }
271  };
272  Stored val_;
273  typename FunImplBase::VTable* vptr_;
274  };
275 
276  // Helper functor creation functions
277 
278 
286  template <typename CallType> inline
288  MakeFunctor(CallType fun)
289  {
291  }
292 
301  template <typename CallType, class PObj> inline
303  MakeFunctor(CallType memfun, PObj* const pobj)
304  {
306  }
307 
315  template <typename CallType, class Fun> inline
316  Functor<typename trUtil::FunTraits<CallType>::ResultType, typename trUtil::FunTraits<CallType>::TypeListType>
317  MakeFunctor(Fun const& fun)
318  {
320  }
321 
330  template <typename CallType, class PObj> inline
331  Functor<typename trUtil::FunTraits<CallType>::ResultType, typename trUtil::FunTraits<CallType>::TypeListType>
332  MakeFunctor(CallType memfun, PObj& pobj)
333  {
335  }
336 }
337 
A null type class.
Definition: TypeList.h:58
typename trUtil::TypeAtNonStrict< TYPELIST_1(const Message_T &), 6, trUtil::NullType >::Result Parm7
Definition: Functor.h:161
Functor(Functor const &src)
Copy constructor.
Definition: Functor.h:84
R operator()() const
Definition: Functor.h:164
R operator()(ParmsListType const &parms) const
Definition: Functor.h:163
Functor(F const &fun)
ctor for static fns and arbitrary functors.
Definition: Functor.h:133
typename trUtil::TypeAtNonStrict< TYPELIST_1(const Message_T &), 3, trUtil::NullType >::Result Parm4
Definition: Functor.h:158
void(* destroy_)(Functor const &)
Definition: Functor.h:179
typename CallParms< TYPELIST_1(const Message_T &) >::ParmsListType ParmsListType
Definition: Functor.h:58
T * init(V const &v)
Definition: Functor.h:234
FunStorageImpl(V const &val)
Definition: Functor.h:189
R operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) const
Definition: Functor.h:169
typename trUtil::TypeAtNonStrict< TYPELIST_1(const Message_T &), 0, trUtil::NullType >::Result Parm1
Definition: Functor.h:155
T * init(V const &v)
Definition: Functor.h:266
void destroy() const
Definition: Functor.h:235
Functor< typename trUtil::FunTraits< CallType >::ResultType, typename trUtil::FunTraits< CallType >::TypeListType > MakeFunctor(CallType fun)
Constructor.
Definition: Functor.h:288
R operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) const
Definition: Functor.h:168
#define DoCall(parms)
Definition: Functor.h:162
R operator()(Parm1 p1, Parm2 p2) const
Definition: Functor.h:166
Function traits.
Definition: FunTraits.h:47
FunctorImpl(T const &val)
Definition: Functor.h:200
static void destroy(Typeless const &val)
Definition: Functor.h:246
R(* call_)(Functor const &, ParmsListType)
Definition: Functor.h:181
bool operator!() const
is-empty selector.
Definition: Functor.h:114
R operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, Parm6 p6) const
Definition: Functor.h:170
void destroy() const
Definition: Functor.h:267
R operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, Parm6 p6, Parm7 p7) const
Definition: Functor.h:171
Stored val_
Definition: Functor.h:272
static void destroy(Typeless const &val)
Definition: Functor.h:254
FunImplBase::VTable * _init(V const &v)
Definition: Functor.h:219
static void Destroy(Functor const &src)
Definition: Functor.h:190
typename trUtil::TypeAtNonStrict< TYPELIST_1(const Message_T &), 2, trUtil::NullType >::Result Parm3
Definition: Functor.h:157
Namespace that holds various utility classes for the engine.
Definition: SmrtPtr.h:208
static FunImplBase::VTable * Clone(Functor const &src, Functor &dest)
Definition: Functor.h:191
FunImplBase::VTable * vptr_
Definition: Functor.h:273
typename trUtil::TypeAtNonStrict< TYPELIST_1(const Message_T &), 4, trUtil::NullType >::Result Parm5
Definition: Functor.h:159
static T * init(Typeless &val, V const &v)
Definition: Functor.h:245
MemberFnImpl(std::pair< P, T > const &val)
Definition: Functor.h:210
bool valid() const
Valids this object.
Definition: Functor.h:123
static T * init(Typeless &val, V const &v)
Definition: Functor.h:253
VTable *(* clone_)(Functor const &, Functor &)
Definition: Functor.h:180
A functor.
Definition: Functor.h:53
typename trUtil::TypeAtNonStrict< TYPELIST_1(const Message_T &), 5, trUtil::NullType >::Result Parm6
Definition: Functor.h:160
Functor()
default construction, assignment and destruction.
Definition: Functor.h:65
R operator()(Parm1 p1, Parm2 p2, Parm3 p3) const
Definition: Functor.h:167
typename trUtil::TypeAtNonStrict< TYPELIST_1(const Message_T &), 1, trUtil::NullType >::Result Parm2
Definition: Functor.h:156
void const * getbuf() const
Definition: Functor.h:239
typename trUtil::Select< sizeof(T)<=sizeof(Typeless), ByValue< T >, NewAlloc< T > >::Result Type
Definition: Functor.h:262
TYPELIST_1(const Message_T &) TypeListType
Definition: Functor.h:57
static R Call(Functor const &src, ParmsListType parms)
Definition: Functor.h:201
R operator()(Parm1 p1) const
Definition: Functor.h:165
Functor(P const &pobj, MF memfun)
ctor for member fns (note: raw ptrs and smart ptrs are equally welcome in pobj)
Definition: Functor.h:149
Functor & operator=(Functor const &src)
Assignment operator.
Definition: Functor.h:98
~Functor()
Destructor.
Definition: Functor.h:72
static R Call(Functor const &src, ParmsListType parms)
Definition: Functor.h:211