siplasplas
A library for C++ reflection and introspection
function.hpp
1 #ifndef SIPLASPLAS_TYPEERASURE_FUNCTION_HPP
2 #define SIPLASPLAS_TYPEERASURE_FUNCTION_HPP
3 
4 #include "simpleany.hpp"
5 #include "anyarg.hpp"
6 #include "invoke.hpp"
7 #include "anystorage/deadpool.hpp"
8 #include "anystorage/fixedsize.hpp"
9 #include <siplasplas/utility/function_traits.hpp>
10 #include <siplasplas/utility/staticif.hpp>
11 #include <siplasplas/utility/compiles.hpp>
12 #include <siplasplas/utility/exception.hpp>
13 
14 namespace cpp
15 {
16 
17 namespace typeerasure
18 {
19 
57 template<typename Storage, typename ArgsStorage = Storage, typename ReturnStorage = Storage>
58 class Function
59 {
60 public:
61  Function() = default;
62 
73  template<typename Callable,
74  typename = std::enable_if_t<!std::is_same<std::decay_t<Callable>, Function>::value>
75  >
76  Function(Callable&& callable) :
77  _invoke{Invoke<std::decay_t<Callable>>{std::forward<Callable>(callable)}}
78  {}
79 
83  bool empty() const
84  {
85  return _invoke.empty();
86  }
87 
96  template<typename Callable, typename... Args>
97  static Function<Storage> create(Args&&... args)
98  {
99  return Function<Storage>{meta::identity<Callable>(), std::forward<Args>(args)...};
100  }
101 
112  template<typename... Args>
114  {
116 
117  AnyArg argsArray[] = {std::forward<Args>(args)..., AnyArg(nullptr)};
118  return _invoke.template get<InvokeInterface>().invoke(std::begin(argsArray));
119  }
120 
131  template<typename... Args>
132  SimpleAny<ReturnStorage> operator()(Args&&... args) const
133  {
135 
136  AnyArg argsArray[] = {std::forward<Args>(args)..., AnyArg(nullptr)};
137  return _invoke.template get<InvokeInterface>().invoke(std::begin(argsArray));
138  }
139 
148  template<typename ArgsVector>
149  SimpleAny<ReturnStorage> invoke(ArgsVector&& args)
150  {
152 
153  return _invoke.template get<InvokeInterface>().invoke(std::forward<ArgsVector>(args));
154  }
155 
164  template<typename ArgsVector>
165  SimpleAny<ReturnStorage> invoke(ArgsVector&& args) const
166  {
168 
169  return _invoke.template get<InvokeInterface>().invoke(std::forward<ArgsVector>(args));
170  }
171 
181  {
183 
184  return _invoke.template get<InvokeInterface>().invoke(args);
185  }
186 
196  {
198 
199  return _invoke.template get<InvokeInterface>().invoke(args);
200  }
201 
205  template<typename Callable>
206  Function& operator=(Callable&& callable)
207  {
208  _invoke = Invoke<std::decay_t<Callable>>{std::forward<Callable>(callable)};
209  return *this;
210  }
211 
216  cpp::FunctionKind kind() const
217  {
218  return _invoke.template get<InvokeInterface>().kind();
219  }
220 
228  template<typename T>
229  const T& get() const
230  {
231  return _invoke.template get<InvokeInterface>().template get<T>();
232  }
233 
241  template<typename T>
242  T& get()
243  {
244  return _invoke.template get<InvokeInterface>().template get<T>();
245  }
246 
247 private:
248  template<typename Callable, typename... Args>
249  Function(meta::identity<Callable>, Args&&... args) :
250  _invoke{Invoke<Callable>{std::forward<Args>(args)...}}
251  {}
252 
253  class InvokeInterface
254  {
255  public:
256  virtual ~InvokeInterface() = default;
257  virtual SimpleAny<ReturnStorage> invoke(std::vector<AnyArg>&& args) = 0;
258  virtual SimpleAny<ReturnStorage> invoke(std::vector<AnyArg>&& args) const = 0;
259  virtual SimpleAny<ReturnStorage> invoke(std::vector<AnyArg>& args) = 0;
260  virtual SimpleAny<ReturnStorage> invoke(std::vector<AnyArg>& args) const = 0;
261  virtual SimpleAny<ReturnStorage> invoke(AnyArg* args) = 0;
262  virtual SimpleAny<ReturnStorage> invoke(AnyArg* args) const = 0;
263  virtual SimpleAny<ReturnStorage> invoke(std::vector<SimpleAny<ArgsStorage>>&& args) = 0;
264  virtual SimpleAny<ReturnStorage> invoke(std::vector<SimpleAny<ArgsStorage>>&& args) const = 0;
265  virtual SimpleAny<ReturnStorage> invoke(std::vector<SimpleAny<ArgsStorage>>& args) = 0;
266  virtual SimpleAny<ReturnStorage> invoke(std::vector<SimpleAny<ArgsStorage>>& args) const = 0;
268  virtual SimpleAny<ReturnStorage> invoke(SimpleAny<ArgsStorage>* args) const = 0;
269 
270  virtual void* getObject() = 0;
271  virtual const void* getObject() const = 0;
272  virtual cpp::FunctionKind kind() const = 0;
273  virtual cpp::typeerasure::TypeInfo typeInfo() const = 0;
274 
275  template<typename T>
276  const T& get() const
277  {
278  SIPLASPLAS_ASSERT(typeInfo() == cpp::typeerasure::TypeInfo::get<std::decay_t<T>>())(
279  "Callable is of type {}, not {}",
280  typeInfo().typeName(),
281  ctti::type_id<std::decay_t<T>>().name()
282  );
283 
284  return *reinterpret_cast<const T*>(getObject());
285  }
286 
287  template<typename T>
288  T& get()
289  {
290  SIPLASPLAS_ASSERT(typeInfo() == cpp::typeerasure::TypeInfo::get<std::decay_t<T>>())(
291  "Callable is of type {}, not {}",
292  typeInfo().typeName(),
293  ctti::type_id<std::decay_t<T>>().name()
294  );
295 
296  return *reinterpret_cast<T*>(getObject());
297  }
298  };
299 
300  template<typename Callable>
301  class Invoke : public InvokeInterface
302  {
303  public:
304  template<typename... Args>
305  Invoke(Args&&... args) :
306  _callable{std::forward<Args>(args)...}
307  {}
308 
309  SimpleAny<ReturnStorage> invoke(std::vector<AnyArg>&& args) override
310  {
311  return doInvoke(std::move(args));
312  }
313 
314  SimpleAny<ReturnStorage> invoke(std::vector<AnyArg>&& args) const override
315  {
316  return doInvoke(std::move(args));
317  }
318 
319  SimpleAny<ReturnStorage> invoke(std::vector<AnyArg>& args) override
320  {
321  return doInvoke(args);
322  }
323 
324  SimpleAny<ReturnStorage> invoke(std::vector<AnyArg>& args) const override
325  {
326  return doInvoke(args);
327  }
328 
329  SimpleAny<ReturnStorage> invoke(AnyArg* args) override
330  {
331  return doInvoke(args);
332  }
333 
334  SimpleAny<ReturnStorage> invoke(AnyArg* args) const override
335  {
336  return doInvoke(args);
337  }
338 
339  SimpleAny<ReturnStorage> invoke(std::vector<SimpleAny<ArgsStorage>>&& args) override
340  {
341  return doInvoke(std::move(args));
342  }
343 
344  SimpleAny<ReturnStorage> invoke(std::vector<SimpleAny<ArgsStorage>>&& args) const override
345  {
346  return doInvoke(std::move(args));
347  }
348 
349  SimpleAny<ReturnStorage> invoke(std::vector<SimpleAny<ArgsStorage>>& args) override
350  {
351  return doInvoke(args);
352  }
353 
354  SimpleAny<ReturnStorage> invoke(std::vector<SimpleAny<ArgsStorage>>& args) const override
355  {
356  return doInvoke(args);
357  }
358 
360  {
361  return doInvoke(args);
362  }
363 
365  {
366  return doInvoke(args);
367  }
368 
369  template<typename Args>
370  SimpleAny<ReturnStorage> doInvoke(Args&& args)
371  {
372  return doInvoke(_callable, std::forward<Args>(args));
373  }
374 
375  template<typename Args>
376  SimpleAny<ReturnStorage> doInvoke(Args&& args) const
377  {
378  return doInvoke(_callable, std::forward<Args>(args));
379  }
380 
381 #define SIPLASPLAS_FUNCTION_INVOKE_EXPRESSION cpp::typeerasure::invoke(identity(std::forward<Callable_>(callable)), identity(std::forward<Args>(args)))
382 
383  template<typename Callable_, typename Args>
384  static SimpleAny<ReturnStorage> doInvoke(Callable_&& callable, Args&& args)
385  {
386  return cpp::staticIf<!(cpp::function_kind<Callable>() == cpp::FunctionKind::MEMBER_FUNCTION && std::is_const<std::remove_reference_t<Args>>::value)>([&](auto identity) -> SimpleAny<ReturnStorage>
387  {
388  return cpp::staticIf<std::is_void<decltype(SIPLASPLAS_FUNCTION_INVOKE_EXPRESSION)>::value>([&](auto identity) -> SimpleAny<ReturnStorage>
389  {
390  SIPLASPLAS_FUNCTION_INVOKE_EXPRESSION;
392  }).Else([&](auto identity) -> SimpleAny<ReturnStorage>
393  {
394  return SIPLASPLAS_FUNCTION_INVOKE_EXPRESSION;
395  });
396  })
397  .Else([](auto) -> SimpleAny<ReturnStorage>
398  {
399  throw cpp::exception<std::runtime_error>(
400  "Cannot invoke a non-const member function with a const vector of arguments"
401  );
402  });
403 
404  }
405 
406 #undef SIPLASPLAS_FUNCTION_INVOKE_EXPRESSION
407 
408  void* getObject() override
409  {
410  return &_callable;
411  }
412 
413  const void* getObject() const override
414  {
415  return &_callable;
416  }
417 
418  cpp::FunctionKind kind() const override
419  {
420  return cpp::function_kind<Callable>();
421  }
422 
423  cpp::typeerasure::TypeInfo typeInfo() const override
424  {
425  return cpp::typeerasure::TypeInfo::get<Callable>();
426  }
427 
428  private:
429  Callable _callable;
430  };
431 
432  SimpleAny32 _invoke;
433 };
434 
435 
441 
447 
453 
459 
460 }
461 
462 }
463 #endif // SIPLASPLAS_TYPEERASURE_FUNCTION_HPP
SimpleAny< ReturnStorage > operator()(Args &&...args)
Invokes the callable with the given arguments.
Definition: function.hpp:113
bool empty() const
Checks if the object is empty (No callable assigned)
Definition: function.hpp:83
Definition: canary_allocator.hpp:7
#define SIPLASPLAS_ASSERT_FALSE(...)
Defines a false assertion.
Definition: assert.hpp:415
static constexpr TypeInfo get()
Returns the type information of type T.
Definition: typeinfo.hpp:224
static Function< Storage > create(Args &&...args)
Creates a Function by instancing in-place the given callable.
Definition: function.hpp:97
Function & operator=(Callable &&callable)
Assigns a new callable to the function.
Definition: function.hpp:206
bool empty() const
Checks whether the any has an object hosted in or if is empty.
Definition: simpleany.hpp:388
Function(Callable &&callable)
Constructs a Function from a Callable object.
Definition: function.hpp:76
SimpleAny< ReturnStorage > invoke(AnyArg *args)
Invokes the callable with the given arguments The arguments are passed as a vector of SimpleAny...
Definition: function.hpp:180
SimpleAny< ReturnStorage > invoke(ArgsVector &&args) const
Invokes the callable with the given arguments The arguments are passed as a vector of SimpleAny...
Definition: function.hpp:165
SimpleAny< ReturnStorage > operator()(Args &&...args) const
Invokes the callable with the given arguments.
Definition: function.hpp:132
Implements a type-erased value container with minimal value semantics requirements.
Definition: simpleany.hpp:15
SimpleAny< ReturnStorage > invoke(ArgsVector &&args)
Invokes the callable with the given arguments The arguments are passed as a vector of SimpleAny...
Definition: function.hpp:149
cpp::FunctionKind kind() const
Returns the function kind (free function, pointer to member function, functor, etc) of the callable...
Definition: function.hpp:216
Contains minimal information to execute the value semantics operations of a type. ...
Definition: typeinfo.hpp:108
Stores a type-erased callable of any signature and kind.
Definition: function.hpp:58
Represents a type erased function call argument.
Definition: anyarg.hpp:31
#define SIPLASPLAS_ASSERT(...)
Defines an assertion expression.
Definition: assert.hpp:212
SimpleAny< ReturnStorage > invoke(AnyArg *args) const
Invokes the callable with the given arguments The arguments are passed as a vector of SimpleAny...
Definition: function.hpp:195