Lumiera  0.pre.03
»edit your freedom«
function.hpp
Go to the documentation of this file.
1 /*
2  FUNCTION.hpp - metaprogramming utilities for transforming function types
3 
4  Copyright (C)
5  2009, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 */
13 
14 
42 #ifndef LIB_META_FUNCTION_H
43 #define LIB_META_FUNCTION_H
44 
45 #include "lib/meta/typelist.hpp"
46 #include "lib/meta/util.hpp"
47 
48 #include <functional>
49 
50 
51 
52 namespace lib {
53 namespace meta{
54 
55  using std::function;
56 
57 
98  template<typename FUN, typename SEL =void>
99  struct _Fun
100  : std::false_type
101  {
102  using Functor = FUN;
103  };
104 
106  template<typename FUN>
107  struct _Fun<FUN, enable_if<has_FunctionOperator<FUN>> >
108  : _Fun<decltype(&FUN::operator())>
109  {
110  using Functor = FUN;
111  };
112 
114  template<typename RET, typename...ARGS>
115  struct _Fun<RET(ARGS...)>
116  : std::true_type
117  {
118  using Ret = RET;
119  using Args = Types<ARGS...>;
120  using Sig = RET(ARGS...);
121  using Functor = std::function<Sig>;
122  enum { ARITY = sizeof...(ARGS) };
123  };
124 
126  template<typename RET, typename...ARGS>
127  struct _Fun<RET(ARGS...) noexcept>
128  : _Fun<RET(ARGS...)>
129  { };
130 
132  template<typename SIG>
133  struct _Fun<SIG*>
134  : _Fun<SIG>
135  { };
136 
138  template<typename SIG>
139  struct _Fun<SIG const&>
140  : _Fun<SIG>
141  { };
142 
144  template<typename SIG>
145  struct _Fun<SIG&>
146  : _Fun<SIG>
147  { };
148 
150  template<typename SIG>
151  struct _Fun<SIG&&>
152  : _Fun<SIG>
153  { };
154 
156  template<class C, typename RET, typename...ARGS>
157  struct _Fun<RET (C::*) (ARGS...)>
158  : _Fun<RET(ARGS...)>
159  { };
160 
162  template<class C, typename RET, typename...ARGS>
163  struct _Fun<RET (C::*) (ARGS...) noexcept>
164  : _Fun<RET(ARGS...)>
165  { };
166 
170  template<class C, typename RET, typename...ARGS>
171  struct _Fun<RET (C::*) (ARGS...) const>
172  : _Fun<RET(ARGS...)>
173  { };
174 
176  template<class C, typename FUN>
177  struct _Fun<FUN (C::*)>
178  : _Fun<FUN>
179  { };
180 
181 
182 
183 
184 
186  template<typename FUN>
187  using _FunRet = typename _Fun<FUN>::Ret;
188 
189  namespace {
190  template<typename FUN>
192  {
193  static_assert(_Fun<FUN>() , "something funktion-like required");
194  static_assert(_Fun<FUN>::ARITY == 1 , "function with exactly one argument required");
195 
196  using Sig = typename _Fun<FUN>::Sig;
197  using Arg = typename _Fun<Sig>::Args::List::Head;
198  };
199  }
200 
202  template<typename FUN>
203  using _FunArg = typename _DetectSingleArgFunction<FUN>::Arg;
204 
205 
206 
207  template<typename FUN, uint a>
208  using has_Arity = std::bool_constant<_Fun<FUN>::ARITY == a>;
209 
210  template<typename FUN>
211  using is_NullaryFun = has_Arity<FUN,0>;
212 
213  template<typename FUN>
214  using is_UnaryFun = has_Arity<FUN,1>;
215 
216  template<typename FUN>
217  using is_BinaryFun = has_Arity<FUN,2>;
218 
219 
220 
221 
222 
231  template<typename FUN, typename SIG, bool =_Fun<FUN>()>
232  struct has_Sig
233  : std::is_same<SIG, typename _Fun<FUN>::Sig>
234  { };
235 
237  template<typename FUN, typename X>
238  struct has_Sig<FUN,X, false>
239  : std::false_type
240  { };
241 
247 #define ASSERT_VALID_SIGNATURE(_FUN_, _SIG_) \
248  static_assert (lib::meta::has_Sig<_FUN_, _SIG_>::value, \
249  "Function " STRINGIFY(_FUN_) " unsuitable, expected signature: " STRINGIFY(_SIG_));
250 
251 
252 
261  template<typename SIG, typename FUN>
262  constexpr inline auto
264  {
265  return has_Sig<FUN,SIG>{};
266  }
267 
273 #define ASSERT_MEMBER_FUNCTOR(_EXPR_, _SIG_) \
274  static_assert (lib::meta::isFunMember<_SIG_>(_EXPR_), \
275  "Member " STRINGIFY(_EXPR_) " unsuitable, expect function signature: " STRINGIFY(_SIG_));
276 
277 
278 
279 
280 
281 
283  template<class TAR>
285 
286  namespace {// Helper to inject instance-pointer instead of placeholder...
291  template<class W, class TAR>
292  constexpr inline TAR*
294  {
295  return static_cast<TAR*> (&instance);
296  }
297 
299  template<class W, typename X>
300  constexpr inline X
301  maybeInject (W&, X&& x)
302  {
303  return std::move(x);
304  }
305  }//(End)Helper for lateBindInstance.
306 
316  template<class W, class TUP>
317  constexpr inline auto
318  lateBindInstance (W& instance, TUP&& invocation)
319  {
320  auto splice = [&instance](auto&& ...xs)
321  {
322  return std::tuple{maybeInject (instance, std::move(xs))...};
323  };
324  return std::apply (splice, std::forward<TUP> (invocation));
325  }
326 
327 
328 
329 
330 
331 
332 
340  template<typename RET, typename ARGS>
341  struct BuildFunType;
342 
343 
344  template< typename RET>
345  struct BuildFunType<RET, Types<> >
346  {
347  using Sig = RET(void);
348  using Fun = _Fun<Sig>;
349  using Func = function<Sig>;
350  using Functor = Func;
351  };
352 
353 
354  template< typename RET
355  , typename A1
356  >
357  struct BuildFunType<RET, Types<A1>>
358  {
359  using Sig = RET(A1);
360  using Fun = _Fun<Sig>;
361  using Func = function<Sig>;
362  using Functor = Func;
363  };
364 
365 
366  template< typename RET
367  , typename A1
368  , typename A2
369  >
370  struct BuildFunType<RET, Types<A1,A2>>
371  {
372  using Sig = RET(A1,A2);
373  using Fun = _Fun<Sig>;
374  using Func = function<Sig>;
375  using Functor = Func;
376  };
377 
378 
379  template< typename RET
380  , typename A1
381  , typename A2
382  , typename A3
383  >
384  struct BuildFunType<RET, Types<A1,A2,A3>>
385  {
386  using Sig = RET(A1,A2,A3);
387  using Fun = _Fun<Sig>;
388  using Func = function<Sig>;
389  using Functor = Func;
390  };
391 
392 
393  template< typename RET
394  , typename A1
395  , typename A2
396  , typename A3
397  , typename A4
398  >
399  struct BuildFunType<RET, Types<A1,A2,A3,A4>>
400  {
401  using Sig = RET(A1,A2,A3,A4);
402  using Fun = _Fun<Sig>;
403  using Func = function<Sig>;
404  using Functor = Func;
405  };
406 
407 
408  template< typename RET
409  , typename A1
410  , typename A2
411  , typename A3
412  , typename A4
413  , typename A5
414  >
415  struct BuildFunType<RET, Types<A1,A2,A3,A4,A5>>
416  {
417  using Sig = RET(A1,A2,A3,A4,A5);
418  using Fun = _Fun<Sig>;
419  using Func = function<Sig>;
420  using Functor = Func;
421  };
422 
423 
424  template< typename RET
425  , typename A1
426  , typename A2
427  , typename A3
428  , typename A4
429  , typename A5
430  , typename A6
431  >
432  struct BuildFunType<RET, Types<A1,A2,A3,A4,A5,A6>>
433  {
434  using Sig = RET(A1,A2,A3,A4,A5,A6);
435  using Fun = _Fun<Sig>;
436  using Func = function<Sig>;
437  using Functor = Func;
438  };
439 
440 
441  template< typename RET
442  , typename A1
443  , typename A2
444  , typename A3
445  , typename A4
446  , typename A5
447  , typename A6
448  , typename A7
449  >
450  struct BuildFunType<RET, Types<A1,A2,A3,A4,A5,A6,A7>>
451  {
452  using Sig = RET(A1,A2,A3,A4,A5,A6,A7);
453  using Fun = _Fun<Sig>;
454  using Func = function<Sig>;
455  using Functor = Func;
456  };
457 
458 
459  template< typename RET
460  , typename A1
461  , typename A2
462  , typename A3
463  , typename A4
464  , typename A5
465  , typename A6
466  , typename A7
467  , typename A8
468  >
469  struct BuildFunType<RET, Types<A1,A2,A3,A4,A5,A6,A7,A8>>
470  {
471  using Sig = RET(A1,A2,A3,A4,A5,A6,A7,A8);
472  using Fun = _Fun<Sig>;
473  using Func = function<Sig>;
474  using Functor = Func;
475  };
476 
477 
478  template< typename RET
479  , typename A1
480  , typename A2
481  , typename A3
482  , typename A4
483  , typename A5
484  , typename A6
485  , typename A7
486  , typename A8
487  , typename A9
488  >
489  struct BuildFunType<RET, Types<A1,A2,A3,A4,A5,A6,A7,A8,A9>>
490  {
491  using Sig = RET(A1,A2,A3,A4,A5,A6,A7,A8,A9);
492  using Fun = _Fun<Sig>;
493  using Func = function<Sig>;
494  using Functor = Func;
495  };
496 
497 
498 
499 
500 
501 }} // namespace lib::meta
502 #endif
Build function types from given Argument types.
Definition: function.hpp:341
constexpr auto lateBindInstance(W &instance, TUP &&invocation)
Fix-up the arguments for a member-function invocation, allowing to inject the actual this instance in...
Definition: function.hpp:318
Meta-function to check that some function like entity offers the expected signature.
Definition: function.hpp:232
A template metaprogramming technique for manipulating collections of types.
Simple and lightweight helpers for metaprogramming and type detection.
Helper for uniform access to function signature types.
Definition: function.hpp:99
constexpr auto isFunMember(FUN)
Helper to pick up a member field for verification.
Definition: function.hpp:263
Implementation namespace for support and library code.
typename enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition: meta/util.hpp:83
Placeholder marker for a special argument position to be supplied later.
Definition: function.hpp:284
typename _DetectSingleArgFunction< FUN >::Arg _FunArg
abbreviation for referring to a function&#39;s single Argument type
Definition: function.hpp:203
typename _Fun< FUN >::Ret _FunRet
abbreviation for referring to a function&#39;s return type
Definition: function.hpp:187
Trait template to detect presence of a simple function call operator.
Definition: meta/util.hpp:215
constexpr X maybeInject(W &, X &&x)
(default case: fall-through)
Definition: function.hpp:301