uTL
micro Template library
invoke.h
Go to the documentation of this file.
1 
20 #ifndef __utl_meta_invoke_h__
21 #define __utl_meta_invoke_h__
22 
23 #include <utl/core/impl.h>
24 #include <utl/meta/integral.h>
25 #include <utl/meta/detection.h>
26 #include <utl/meta/operations.h>
27 
33 namespace utl {
35 namespace meta{
36 
47 
52  template <typename _Tp>
54  struct identity {
55  #if defined (UTL_WORKAROUND_CWG_1558)
56  // redirect unused Ts... via void_t
57  template <typename... Ts>
58  using apply = first_of<_Tp, void_t<Ts...>>;
59  #else
60  template <typename...>
61  using apply = _Tp;
62  #endif
63  using type = _Tp;
64  };
65 
67  template <typename _Tp>
70 
74 
80  template <typename Fn, typename... Args>
81  using invoke = typename Fn::template apply<Args...>;
82 
87  template <typename Fn, typename... Args>
88  using invoke_t = eval< invoke <Fn, Args...>>;
90 
93 
99  template <template <typename...> class F>
100  struct wrap {
101  template <typename... Args>
102  using apply = F<Args...>;
103  };
104 
106  template <typename T, template <T...> class F>
107  struct wrap_i {
108  // requires meta::Integral
109  template <typename... Ts>
110  using apply = F<Ts::type::value...>;
111  };
113 
116  namespace detail {
117 
118  template<template<typename...> class F, typename... T>
119  struct is_applicable_ {
120  template<template<typename...> class G, typename = G<T...>>
121  static true_ check (int); //< T.. can be passed to G
122  template<template<typename...> class>
123  static false_ check (...); //< all other combinations
124 
125  using type = decltype(check<F>(0));
126  };
127 
128  template<typename F, typename... T>
130  template<typename G, typename Ret = invoke_t<G, T...>>
131  static Ret check (int); //< T.. can be passed to G
132  template<typename...>
133  static nil_ check (...); //< all other combinations
134 
135  using type = if_ <
136  not_same_<
137  nil_,
138  decltype(check<F>(0))
139  >, true_, false_
140  >;
146  };
147 
148  template<typename T, template <T...> class F, T... Is>
150  template<typename TT, template<TT...> class G, typename = G<Is...>>
151  static true_ check (int); //< Is... can be passed to G
152  template<typename TT, template<TT...> class G>
153  static false_ check (...); //< all other combinations
154 
155  using type = decltype(check<T, F>(0));
156  };
157  }
158 
160  template<template<typename...> class F, typename... T>
161  using is_applicable_t = eval<
162  detail::is_applicable_<F, T...>
163  >;
165  template<typename Q, typename... T>
166  using is_applicable_qt = eval <
167  detail::is_applicable_q_ <Q, T...>
168  >;
169 
171  template <typename T, template<T...> class F, T... Is>
172  using is_applicable_it = eval<
173  detail::is_applicable_i_<T, F, Is...>
174  >;
175 
177 
180  namespace detail {
182  template<template<typename...> class F, typename... Ts>
183  struct defer_ {
184  using type = F<Ts...>;
185  };
186 
187  template<typename T, template<T...> class F, T... Is>
188  struct defer_i_ {
189  using type = F<Is...>;
190  };
191 
205  }
206 
208  template<template<class...> class F, class... Ts>
209  using defer = if_<
210  detail::is_applicable_<F, Ts...>,
211  detail::defer_<F, Ts...>,
212  nil_
213  >;
214 
216  template <typename T, template<T...> class F, T... Is>
217  using defer_i = if_ <
218  detail::is_applicable_i_<T, F, Is...>,
219  detail::defer_i_<T, F, Is...>,
220  nil_
221  >;
223 
226 
233  template <template <typename...> class F>
234  struct quote {
235  template <typename... Args>
236  using apply = eval<
237  defer<F, Args...>
238  >;
239  };
240 
242  template <typename T, template <T...> class F>
243  struct quote_i {
244  // requires meta::Integral
245  template <typename... Ts>
246  using apply = eval<
247  defer_i<T, F, Ts::type::value...>
248  >;
249  };
251 
254  namespace detail {
255  template <template <typename...> class... Fns> struct compose_f_ {};
256 
257  // recursive call to all invokes
258  template <template <typename...> class Fn0,
259  template <typename...> class... Fns>
260  struct compose_f_<Fn0, Fns...> {
261  template <typename... Args>
262  using apply = invoke<
263  quote<Fn0>,
264  invoke<compose_f_<Fns...>, Args...>
265  >;
266  };
267  // Termination specialization, finally pass the arguments
268  template <template <typename...> class Fn0>
269  struct compose_f_<Fn0> {
270  template <typename ...Args>
271  using apply = invoke<quote<Fn0>, Args...>;
272  };
273 
274 
275  template<typename ...Fns> struct compose_ {};
276 
277  // recursive call to all invokes
278  template<typename Fn0, typename ...Fns>
279  struct compose_<Fn0, Fns...> {
280  template <typename ...Args>
281  using apply = invoke<
282  Fn0,
283  invoke<compose_<Fns...>, Args...>
284  >;
285  };
286  // Termination specialization, finally pass the arguments
287  template<typename Fn0>
288  struct compose_<Fn0> {
289  template <typename... Args>
290  using apply = invoke<Fn0, Args...>;
291  };
292  }
293 
307  template <typename... Fns>
308  using compose = detail::compose_<Fns...>;
309 
323  template <template <typename...> class... Fns>
324  using compose_f = detail::compose_f_<Fns...>;
326 
331  template<typename Fn, typename... Ts>
332  struct bind_front {
333  template<typename... Us>
334  using apply = invoke<Fn, Ts..., Us...>;
335  };
336 
341  template<typename Fn, typename... Ts>
342  struct bind_back {
343  template<typename... Us>
344  using apply = invoke<Fn, Us..., Ts...>;
345  };
346 
347 
348  /*
349  * ========== meta:: predicates ============
350  */
351  template <typename T1>
352  struct same_as {
353  template <typename T2>
354  struct apply : same_<T1, T2> { };
355  };
356 
357  template <typename T1>
358  struct not_same_as {
359  template <typename T2>
360  struct apply : not_same_<T1, T2> { };
361  };
362 
363 }}
364 
367 
368 #endif /* __utl_meta_invoke_h__ */
F< Args... > apply
Definition: invoke.h:102
if_< detail::is_applicable_< F, Ts... >, detail::defer_< F, Ts... >, nil_ > defer
defer alias template for F<Ts...>
Definition: invoke.h:213
T1 first_of
Select the first type of a type sequence.
Definition: selection.h:76
eval< detail::is_applicable_q_< Q, T... > > is_applicable_qt
check if we can invoke Q with parameters T
Definition: invoke.h:168
if_c< If::type::value, Args... > if_
Select one type or another depending on a compile-time Boolean type.
Definition: selection.h:66
void void_t
void_t type alias
Definition: detection.h:55
_Tp type
identity
Definition: invoke.h:63
if_< detail::is_applicable_i_< T, F, Is... >, detail::defer_i_< T, F, Is... >, nil_ > defer_i
defer_i alias template for F<T, Is...>
Definition: invoke.h:221
bool_< true > true_
The type used as a compile-time boolean with true value.
Definition: integral.h:68
Integral constant operations and logical operations.
invoke< Fn0, invoke< compose_< Fns... >, Args... > > apply
Definition: invoke.h:284
F< Ts::type::value... > apply
Definition: invoke.h:110
invoke< Fn, Ts..., Us... > apply
Definition: invoke.h:334
invoke< quote< Fn0 >, Args... > apply
Definition: invoke.h:271
bool_< false > false_
The type used as a compile-time boolean with false value.
Definition: integral.h:69
Wrap a template F taking literal constants of type T into an Invokable.
Definition: invoke.h:243
typename Tp::type eval
Type alias for Tp::type. Used to evaluate/extract return type of metafunctions.
Definition: integral.h:49
decltype(check< F >(0)) type
Definition: invoke.h:125
Detection idiom based on WG21&#39;s N4502 [n4502 1] from Walter E. Brown.
invoke< Fn0, Args... > apply
Definition: invoke.h:290
STL&#39;s core language concepts.
Definition: _1wire.h:30
eval< defer_i< T, F, Ts::type::value... > > apply
Definition: invoke.h:248
if_< not_same_< nil_, decltype(check< F >(0)) >, true_, false_ > type
Definition: invoke.h:140
eval< detail::is_applicable_< F, T... > > is_applicable_t
check if we can instantiate F with parameters T
Definition: invoke.h:163
eval< identity< _Tp > > identity_t
identity type alias
Definition: invoke.h:68
eval< detail::is_applicable_i_< T, F, Is... > > is_applicable_it
check if we can instantiate F with parameters Is of type T
Definition: invoke.h:174
not_< eval< same_< _T1, _T2 > >> not_same_
Definition: operations.h:111
eval< invoke< Fn, Args... > > invoke_t
Definition: invoke.h:88
typename Fn::template apply< Args... > invoke
Definition: invoke.h:81
invoke< Fn, Us..., Ts... > apply
Definition: invoke.h:344
_Tp apply
identity is invokable, must also have apply
Definition: invoke.h:61
decltype(check< T, F >(0)) type
Definition: invoke.h:155
Wrap a template F taking literal constants of type T into an Invokable.
Definition: invoke.h:107
invoke< quote< Fn0 >, invoke< compose_f_< Fns... >, Args... > > apply
Definition: invoke.h:265
Implementation detail main forward header.
eval< defer< F, Args... > > apply
Definition: invoke.h:238