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) Lumiera.org
5  2009, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
51 #ifndef LIB_META_FUNCTION_H
52 #define LIB_META_FUNCTION_H
53 
54 #include "lib/meta/typelist.hpp"
55 #include "lib/meta/util.hpp"
56 
57 #include <functional>
58 
59 
60 
61 namespace lib {
62 namespace meta{
63 
64  using std::function;
65 
66 
107  template<typename FUN, typename SEL =void>
108  struct _Fun
109  : std::false_type
110  {
111  using Functor = FUN;
112  };
113 
115  template<typename FUN>
116  struct _Fun<FUN, enable_if<has_FunctionOperator<FUN>> >
117  : _Fun<decltype(&FUN::operator())>
118  {
119  using Functor = FUN;
120  };
121 
123  template<typename RET, typename...ARGS>
124  struct _Fun<RET(ARGS...)>
125  : std::true_type
126  {
127  using Ret = RET;
128  using Args = Types<ARGS...>;
129  using Sig = RET(ARGS...);
130  using Functor = std::function<Sig>;
131  enum { ARITY = sizeof...(ARGS) };
132  };
133 
135  template<typename RET, typename...ARGS>
136  struct _Fun<RET(ARGS...) noexcept>
137  : _Fun<RET(ARGS...)>
138  { };
139 
141  template<typename SIG>
142  struct _Fun<SIG*>
143  : _Fun<SIG>
144  { };
145 
147  template<typename SIG>
148  struct _Fun<SIG const&>
149  : _Fun<SIG>
150  { };
151 
153  template<typename SIG>
154  struct _Fun<SIG&>
155  : _Fun<SIG>
156  { };
157 
159  template<typename SIG>
160  struct _Fun<SIG&&>
161  : _Fun<SIG>
162  { };
163 
165  template<class C, typename RET, typename...ARGS>
166  struct _Fun<RET (C::*) (ARGS...)>
167  : _Fun<RET(ARGS...)>
168  { };
169 
171  template<class C, typename RET, typename...ARGS>
172  struct _Fun<RET (C::*) (ARGS...) noexcept>
173  : _Fun<RET(ARGS...)>
174  { };
175 
179  template<class C, typename RET, typename...ARGS>
180  struct _Fun<RET (C::*) (ARGS...) const>
181  : _Fun<RET(ARGS...)>
182  { };
183 
185  template<class C, typename FUN>
186  struct _Fun<FUN (C::*)>
187  : _Fun<FUN>
188  { };
189 
190 
191 
192 
193 
195  template<typename FUN>
196  using _FunRet = typename _Fun<FUN>::Ret;
197 
198  namespace {
199  template<typename FUN>
201  {
202  static_assert(_Fun<FUN>() , "something funktion-like required");
203  static_assert(_Fun<FUN>::ARITY == 1 , "function with exactly one argument required");
204 
205  using Sig = typename _Fun<FUN>::Sig;
206  using Arg = typename _Fun<Sig>::Args::List::Head;
207  };
208  }
209 
211  template<typename FUN>
212  using _FunArg = typename _DetectSingleArgFunction<FUN>::Arg;
213 
214 
215 
216  template<typename FUN, uint a>
217  using has_Arity = std::bool_constant<_Fun<FUN>::ARITY == a>;
218 
219  template<typename FUN>
220  using is_NullaryFun = has_Arity<FUN,0>;
221 
222  template<typename FUN>
223  using is_UnaryFun = has_Arity<FUN,1>;
224 
225  template<typename FUN>
226  using is_BinaryFun = has_Arity<FUN,2>;
227 
228 
229 
230 
231 
240  template<typename FUN, typename SIG, bool =_Fun<FUN>()>
241  struct has_Sig
242  : std::is_same<SIG, typename _Fun<FUN>::Sig>
243  { };
244 
246  template<typename FUN, typename X>
247  struct has_Sig<FUN,X, false>
248  : std::false_type
249  { };
250 
256 #define ASSERT_VALID_SIGNATURE(_FUN_, _SIG_) \
257  static_assert (lib::meta::has_Sig<_FUN_, _SIG_>::value, \
258  "Function " STRINGIFY(_FUN_) " unsuitable, expected signature: " STRINGIFY(_SIG_));
259 
260 
261 
270  template<typename SIG, typename FUN>
271  constexpr inline auto
273  {
274  return has_Sig<FUN,SIG>{};
275  }
276 
282 #define ASSERT_MEMBER_FUNCTOR(_EXPR_, _SIG_) \
283  static_assert (lib::meta::isFunMember<_SIG_>(_EXPR_), \
284  "Member " STRINGIFY(_EXPR_) " unsuitable, expect function signature: " STRINGIFY(_SIG_));
285 
286 
287 
288 
289 
290 
292  template<class TAR>
294 
295  namespace {// Helper to inject instance-pointer instead of placeholder...
300  template<class W, class TAR>
301  constexpr inline TAR*
303  {
304  return static_cast<TAR*> (&instance);
305  }
306 
308  template<class W, typename X>
309  constexpr inline X
310  maybeInject (W&, X&& x)
311  {
312  return std::move(x);
313  }
314  }//(End)Helper for lateBindInstance.
315 
325  template<class W, class TUP>
326  constexpr inline auto
327  lateBindInstance (W& instance, TUP&& invocation)
328  {
329  auto splice = [&instance](auto&& ...xs)
330  {
331  return std::tuple{maybeInject (instance, std::move(xs))...};
332  };
333  return std::apply (splice, std::forward<TUP> (invocation));
334  }
335 
336 
337 
338 
339 
340 
341 
349  template<typename RET, typename ARGS>
350  struct BuildFunType;
351 
352 
353  template< typename RET>
354  struct BuildFunType<RET, Types<> >
355  {
356  using Sig = RET(void);
357  using Fun = _Fun<Sig>;
358  using Func = function<Sig>;
359  using Functor = Func;
360  };
361 
362 
363  template< typename RET
364  , typename A1
365  >
366  struct BuildFunType<RET, Types<A1>>
367  {
368  using Sig = RET(A1);
369  using Fun = _Fun<Sig>;
370  using Func = function<Sig>;
371  using Functor = Func;
372  };
373 
374 
375  template< typename RET
376  , typename A1
377  , typename A2
378  >
379  struct BuildFunType<RET, Types<A1,A2>>
380  {
381  using Sig = RET(A1,A2);
382  using Fun = _Fun<Sig>;
383  using Func = function<Sig>;
384  using Functor = Func;
385  };
386 
387 
388  template< typename RET
389  , typename A1
390  , typename A2
391  , typename A3
392  >
393  struct BuildFunType<RET, Types<A1,A2,A3>>
394  {
395  using Sig = RET(A1,A2,A3);
396  using Fun = _Fun<Sig>;
397  using Func = function<Sig>;
398  using Functor = Func;
399  };
400 
401 
402  template< typename RET
403  , typename A1
404  , typename A2
405  , typename A3
406  , typename A4
407  >
408  struct BuildFunType<RET, Types<A1,A2,A3,A4>>
409  {
410  using Sig = RET(A1,A2,A3,A4);
411  using Fun = _Fun<Sig>;
412  using Func = function<Sig>;
413  using Functor = Func;
414  };
415 
416 
417  template< typename RET
418  , typename A1
419  , typename A2
420  , typename A3
421  , typename A4
422  , typename A5
423  >
424  struct BuildFunType<RET, Types<A1,A2,A3,A4,A5>>
425  {
426  using Sig = RET(A1,A2,A3,A4,A5);
427  using Fun = _Fun<Sig>;
428  using Func = function<Sig>;
429  using Functor = Func;
430  };
431 
432 
433  template< typename RET
434  , typename A1
435  , typename A2
436  , typename A3
437  , typename A4
438  , typename A5
439  , typename A6
440  >
441  struct BuildFunType<RET, Types<A1,A2,A3,A4,A5,A6>>
442  {
443  using Sig = RET(A1,A2,A3,A4,A5,A6);
444  using Fun = _Fun<Sig>;
445  using Func = function<Sig>;
446  using Functor = Func;
447  };
448 
449 
450  template< typename RET
451  , typename A1
452  , typename A2
453  , typename A3
454  , typename A4
455  , typename A5
456  , typename A6
457  , typename A7
458  >
459  struct BuildFunType<RET, Types<A1,A2,A3,A4,A5,A6,A7>>
460  {
461  using Sig = RET(A1,A2,A3,A4,A5,A6,A7);
462  using Fun = _Fun<Sig>;
463  using Func = function<Sig>;
464  using Functor = Func;
465  };
466 
467 
468  template< typename RET
469  , typename A1
470  , typename A2
471  , typename A3
472  , typename A4
473  , typename A5
474  , typename A6
475  , typename A7
476  , typename A8
477  >
478  struct BuildFunType<RET, Types<A1,A2,A3,A4,A5,A6,A7,A8>>
479  {
480  using Sig = RET(A1,A2,A3,A4,A5,A6,A7,A8);
481  using Fun = _Fun<Sig>;
482  using Func = function<Sig>;
483  using Functor = Func;
484  };
485 
486 
487  template< typename RET
488  , typename A1
489  , typename A2
490  , typename A3
491  , typename A4
492  , typename A5
493  , typename A6
494  , typename A7
495  , typename A8
496  , typename A9
497  >
498  struct BuildFunType<RET, Types<A1,A2,A3,A4,A5,A6,A7,A8,A9>>
499  {
500  using Sig = RET(A1,A2,A3,A4,A5,A6,A7,A8,A9);
501  using Fun = _Fun<Sig>;
502  using Func = function<Sig>;
503  using Functor = Func;
504  };
505 
506 
507 
508 
509 
510 }} // namespace lib::meta
511 #endif
Build function types from given Argument types.
Definition: function.hpp:350
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:327
Meta-function to check that some function like entity offers the expected signature.
Definition: function.hpp:241
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:108
constexpr auto isFunMember(FUN)
Helper to pick up a member field for verification.
Definition: function.hpp:272
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:92
Placeholder marker for a special argument position to be supplied later.
Definition: function.hpp:293
typename _DetectSingleArgFunction< FUN >::Arg _FunArg
abbreviation for referring to a function&#39;s single Argument type
Definition: function.hpp:212
typename _Fun< FUN >::Ret _FunRet
abbreviation for referring to a function&#39;s return type
Definition: function.hpp:196
Trait template to detect presence of a simple function call operator.
Definition: meta/util.hpp:224
constexpr X maybeInject(W &, X &&x)
(default case: fall-through)
Definition: function.hpp:310