invoke.h
Go to the documentation of this file.
#ifndef __utl_meta_invoke_h__
#define __utl_meta_invoke_h__
#include <utl/core/impl.h>
#include <utl/meta/integral.h>
#include <utl/meta/detection.h>
#include <utl/meta/operations.h>
namespace utl {
namespace meta{
template <typename _Tp>
struct identity {
#if defined (UTL_WORKAROUND_CWG_1558)
// redirect unused Ts... via void_t
template <typename... Ts>
using apply = first_of<_Tp, void_t<Ts...>>;
#else
template <typename...>
using apply = _Tp;
#endif
using type = _Tp;
};
template <typename _Tp>
using identity_t = eval<identity<_Tp>>;
template <typename Fn, typename... Args>
using invoke = typename Fn::template apply<Args...>;
template <typename Fn, typename... Args>
using invoke_t = eval< invoke <Fn, Args...>>;
template <template <typename...> class F>
struct wrap {
template <typename... Args>
using apply = F<Args...>;
};
template <typename T, template <T...> class F>
struct wrap_i {
// requires meta::Integral
template <typename... Ts>
using apply = F<Ts::type::value...>;
};
namespace detail {
template<template<typename...> class F, typename... T>
struct is_applicable_ {
template<template<typename...> class G, typename = G<T...>>
static true_ check (int); //< T.. can be passed to G
template<template<typename...> class>
static false_ check (...); //< all other combinations
using type = decltype(check<F>(0));
};
template<typename F, typename... T>
struct is_applicable_q_ {
template<typename G, typename Ret = invoke_t<G, T...>>
static Ret check (int); //< T.. can be passed to G
template<typename...>
static nil_ check (...); //< all other combinations
using type = if_ <
not_same_<
nil_,
decltype(check<F>(0))
>, true_, false_
>;
};
template<typename T, template <T...> class F, T... Is>
struct is_applicable_i_ {
template<typename TT, template<TT...> class G, typename = G<Is...>>
static true_ check (int); //< Is... can be passed to G
template<typename TT, template<TT...> class G>
static false_ check (...); //< all other combinations
using type = decltype(check<T, F>(0));
};
}
template<template<typename...> class F, typename... T>
using is_applicable_t = eval<
detail::is_applicable_<F, T...>
>;
template<typename Q, typename... T>
using is_applicable_qt = eval <
detail::is_applicable_q_ <Q, T...>
>;
template <typename T, template<T...> class F, T... Is>
using is_applicable_it = eval<
detail::is_applicable_i_<T, F, Is...>
>;
namespace detail {
template<template<typename...> class F, typename... Ts>
struct defer_ {
using type = F<Ts...>;
};
template<typename T, template<T...> class F, T... Is>
struct defer_i_ {
using type = F<Is...>;
};
}
template<template<class...> class F, class... Ts>
using defer = if_<
detail::is_applicable_<F, Ts...>,
detail::defer_<F, Ts...>,
nil_
>;
template <typename T, template<T...> class F, T... Is>
using defer_i = if_ <
detail::is_applicable_i_<T, F, Is...>,
detail::defer_i_<T, F, Is...>,
nil_
>;
template <template <typename...> class F>
struct quote {
template <typename... Args>
using apply = eval<
defer<F, Args...>
>;
};
template <typename T, template <T...> class F>
struct quote_i {
// requires meta::Integral
template <typename... Ts>
using apply = eval<
defer_i<T, F, Ts::type::value...>
>;
};
namespace detail {
template <template <typename...> class... Fns> struct compose_f_ {};
// recursive call to all invokes
template <template <typename...> class Fn0,
template <typename...> class... Fns>
struct compose_f_<Fn0, Fns...> {
template <typename... Args>
using apply = invoke<
quote<Fn0>,
invoke<compose_f_<Fns...>, Args...>
>;
};
// Termination specialization, finally pass the arguments
template <template <typename...> class Fn0>
struct compose_f_<Fn0> {
template <typename ...Args>
using apply = invoke<quote<Fn0>, Args...>;
};
template<typename ...Fns> struct compose_ {};
// recursive call to all invokes
template<typename Fn0, typename ...Fns>
struct compose_<Fn0, Fns...> {
template <typename ...Args>
using apply = invoke<
Fn0,
invoke<compose_<Fns...>, Args...>
>;
};
// Termination specialization, finally pass the arguments
template<typename Fn0>
struct compose_<Fn0> {
template <typename... Args>
using apply = invoke<Fn0, Args...>;
};
}
template <typename... Fns>
using compose = detail::compose_<Fns...>;
template <template <typename...> class... Fns>
using compose_f = detail::compose_f_<Fns...>;
template<typename Fn, typename... Ts>
struct bind_front {
template<typename... Us>
using apply = invoke<Fn, Ts..., Us...>;
};
template<typename Fn, typename... Ts>
struct bind_back {
template<typename... Us>
using apply = invoke<Fn, Us..., Ts...>;
};
/*
* ========== meta:: predicates ============
*/
template <typename T1>
struct same_as {
template <typename T2>
struct apply : same_<T1, T2> { };
};
template <typename T1>
struct not_same_as {
template <typename T2>
struct apply : not_same_<T1, T2> { };
};
}}
#endif /* __utl_meta_invoke_h__ */
utl::meta::wrap::apply
F< Args... > apply
Definition: invoke.h:102
utl::meta::defer
if_< detail::is_applicable_< F, Ts... >, detail::defer_< F, Ts... >, nil_ > defer
defer alias template for F<Ts...>
Definition: invoke.h:213
utl::meta::first_of
T1 first_of
Select the first type of a type sequence.
Definition: selection.h:76
utl::meta::detail::defer_
Definition: invoke.h:183
utl::meta::is_applicable_qt
eval< detail::is_applicable_q_< Q, T... > > is_applicable_qt
check if we can invoke Q with parameters T
Definition: invoke.h:168
utl::meta::if_
if_c< If::type::value, Args... > if_
Select one type or another depending on a compile-time Boolean type.
Definition: selection.h:66
utl::meta::void_t
void void_t
void_t type alias
Definition: detection.h:55
utl::meta::identity::type
_Tp type
identity
Definition: invoke.h:63
utl::meta::defer_i
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
utl::meta::quote
Definition: invoke.h:234
utl::meta::identity
Definition: invoke.h:54
utl::meta::true_
bool_< true > true_
The type used as a compile-time boolean with true value.
Definition: integral.h:68
utl::meta::detail::is_applicable_::check
static true_ check(int)
operations.h
Integral constant operations and logical operations.
utl::meta::detail::compose_< Fn0, Fns... >::apply
invoke< Fn0, invoke< compose_< Fns... >, Args... > > apply
Definition: invoke.h:284
utl::meta::wrap_i::apply
F< Ts::type::value... > apply
Definition: invoke.h:110
utl::meta::wrap
Definition: invoke.h:100
utl::meta::detail::is_applicable_i_
Definition: invoke.h:149
utl::meta::nil_
Definition: integral.h:43
utl::meta::bind_front::apply
invoke< Fn, Ts..., Us... > apply
Definition: invoke.h:334
utl::meta::detail::compose_f_< Fn0 >::apply
invoke< quote< Fn0 >, Args... > apply
Definition: invoke.h:271
utl::meta::detail::is_applicable_q_
Definition: invoke.h:129
utl::meta::false_
bool_< false > false_
The type used as a compile-time boolean with false value.
Definition: integral.h:69
utl::meta::quote_i
Wrap a template F taking literal constants of type T into an Invokable.
Definition: invoke.h:243
utl::meta::eval
typename Tp::type eval
Type alias for Tp::type. Used to evaluate/extract return type of metafunctions.
Definition: integral.h:49
utl::meta::not_same_as
Definition: invoke.h:358
utl::meta::detail::is_applicable_::type
decltype(check< F >(0)) type
Definition: invoke.h:125
detection.h
Detection idiom based on WG21&#39;s N4502 [n4502 1] from Walter E. Brown.
utl::meta::detail::compose_< Fn0 >::apply
invoke< Fn0, Args... > apply
Definition: invoke.h:290
utl
STL&#39;s core language concepts.
Definition: _1wire.h:30
utl::meta::not_same_as::apply
Definition: invoke.h:360
utl::meta::apply_impl::apply_
Definition: typelist.h:172
utl::meta::same_
Definition: operations.h:102
utl::meta::detail::compose_
Definition: invoke.h:275
utl::meta::quote_i::apply
eval< defer_i< T, F, Ts::type::value... > > apply
Definition: invoke.h:248
utl::meta::detail::is_applicable_q_::type
if_< not_same_< nil_, decltype(check< F >(0)) >, true_, false_ > type
Definition: invoke.h:140
integral.h
utl::meta::detail::is_applicable_i_::check
static true_ check(int)
utl::meta::is_applicable_t
eval< detail::is_applicable_< F, T... > > is_applicable_t
check if we can instantiate F with parameters T
Definition: invoke.h:163
utl::meta::detail::compose_f_
Definition: invoke.h:255
utl::meta::bind_back
Definition: invoke.h:342
utl::meta::detail::defer_i_::type
F< Is... > type
Definition: invoke.h:189
utl::meta::identity_t
eval< identity< _Tp > > identity_t
identity type alias
Definition: invoke.h:68
utl::meta::detail::defer_::type
F< Ts... > type
Definition: invoke.h:184
utl::meta::same_as
Definition: invoke.h:352
utl::meta::is_applicable_it
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
utl::meta::not_same_
not_< eval< same_< _T1, _T2 > >> not_same_
Definition: operations.h:111
utl::meta::invoke_t
eval< invoke< Fn, Args... > > invoke_t
Definition: invoke.h:88
utl::meta::invoke
typename Fn::template apply< Args... > invoke
Definition: invoke.h:81
utl::meta::bind_back::apply
invoke< Fn, Us..., Ts... > apply
Definition: invoke.h:344
utl::meta::detail::defer_i_
Definition: invoke.h:188
utl::meta::identity::apply
_Tp apply
identity is invokable, must also have apply
Definition: invoke.h:61
utl::meta::detail::is_applicable_i_::type
decltype(check< T, F >(0)) type
Definition: invoke.h:155
utl::meta::wrap_i
Wrap a template F taking literal constants of type T into an Invokable.
Definition: invoke.h:107
utl::meta::detail::compose_f_< Fn0, Fns... >::apply
invoke< quote< Fn0 >, invoke< compose_f_< Fns... >, Args... > > apply
Definition: invoke.h:265
utl::meta::bind_front
Definition: invoke.h:332
utl::meta::same_as::apply
Definition: invoke.h:354
impl.h
Implementation detail main forward header.
utl::meta::detail::is_applicable_q_::check
static Ret check(int)
utl::meta::quote::apply
eval< defer< F, Args... > > apply
Definition: invoke.h:238
utl::meta::detail::is_applicable_
Definition: invoke.h:119