meta: minor changes to invoke
This commit is contained in:
parent
903e4641f4
commit
bb35115359
@ -66,14 +66,13 @@ namespace meta{
|
||||
template <typename _Tp>
|
||||
struct identity {
|
||||
#if defined (UTL_WORKAROUND_CWG_1558)
|
||||
// decltype via use_() using Ts... to set the apply type
|
||||
// redirect unused Ts... via void_t
|
||||
template <typename... Ts>
|
||||
using _dummy = void_t<Ts...>;
|
||||
using apply = _Tp; //!< identity is invokable, must also have apply
|
||||
using apply = first_of<_Tp, void_t<Ts...>>; //!< identity is invokable, must also have apply
|
||||
#else
|
||||
template <typename...>
|
||||
using apply = _Tp; //!< identity is invokable, must also have apply
|
||||
#endif
|
||||
#endif
|
||||
using type = _Tp; //!< identity
|
||||
};
|
||||
|
||||
@ -82,40 +81,68 @@ namespace meta{
|
||||
using identity_t = type_<identity<_Tp>>;
|
||||
//! @}
|
||||
|
||||
//! Is evaluable trait
|
||||
//! Is applicable trait
|
||||
//! @{
|
||||
namespace detail {
|
||||
|
||||
// we check for template \p F to be a metafunction with parameters \p T
|
||||
template<template<typename...> class F, typename... T>
|
||||
struct is_evaluable_ {
|
||||
struct is_applicable_ {
|
||||
template<template<typename...> class G, typename = G<T...>>
|
||||
static true_ check (int);
|
||||
static true_ check (int); //< T.. can be passed to G
|
||||
template<template<typename...> class>
|
||||
static false_ check (...);
|
||||
static false_ check (...); //< all other combinations
|
||||
|
||||
using type = decltype(check<F>(0));
|
||||
};
|
||||
|
||||
// we check for template \p F with integral constant parameters \p Is of type \p T
|
||||
// template<typename T, template <T...> class F, T... Is>
|
||||
// struct is_evaluable_i_ {
|
||||
// template<typename TT, template <TT...> class G, class = G<Is...>>
|
||||
// static true_ check (int);
|
||||
// template<typename, template<typename...> class>
|
||||
// static false_ check (...);
|
||||
//
|
||||
// using type = decltype(check<T, F>(0));
|
||||
// };
|
||||
template <typename Fn, typename... Args>
|
||||
using use_ = typename Fn::template apply<Args...>;
|
||||
|
||||
template<typename F, typename... T>
|
||||
struct is_applicable_q_ {
|
||||
template<typename G, typename Ret= type_<use_<G, T...>>>
|
||||
static Ret check (int); //< T.. can be passed to G
|
||||
template<typename...>
|
||||
static nil_ check (...); //< all other combinations
|
||||
|
||||
using type = decltype(check<F>(0));
|
||||
};
|
||||
|
||||
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));
|
||||
};
|
||||
}
|
||||
|
||||
//! check if we can instantiate \p F with parameters \p T
|
||||
template<template<typename...> class F, typename... T>
|
||||
using is_evaluable = type_<
|
||||
detail::is_evaluable_<F, T...>
|
||||
using is_applicable_t = type_<
|
||||
detail::is_applicable_<F, T...>
|
||||
>;
|
||||
//! check if we can instantiate \p Q with parameters \p T and the instant
|
||||
//! is different from \c nil_
|
||||
template<typename Q, typename... T>
|
||||
using is_applicable_qt = type_ <
|
||||
// Extra check for quoted metafunctions to check return type
|
||||
if_ <
|
||||
not_same_<
|
||||
type_ <detail::is_applicable_q_ <Q, T...>>,
|
||||
nil_
|
||||
>,
|
||||
true_,
|
||||
false_
|
||||
>
|
||||
>;
|
||||
//! check if we can instantiate \p F with parameters \p Is of type \p T
|
||||
template <typename T, template<T...> class F, T... Is>
|
||||
using is_applicable_it = type_<
|
||||
detail::is_applicable_i_<T, F, Is...>
|
||||
>;
|
||||
|
||||
// template <typename T, template<T...> class F, T... Is>
|
||||
// using is_evaluable_i = type_<detail::is_evaluable_i_<T, F<Is...>>>;
|
||||
|
||||
//! @}
|
||||
|
||||
@ -128,11 +155,12 @@ namespace meta{
|
||||
using type = F<Ts...>;
|
||||
};
|
||||
|
||||
// template<typename T, template<T...> class F, T... Is>
|
||||
// struct defer_i_ {
|
||||
// using type = F<Is...>;
|
||||
// };
|
||||
//!
|
||||
template<typename T, template<T...> class F, T... Is>
|
||||
struct defer_i_ {
|
||||
using type = F<Is...>;
|
||||
};
|
||||
|
||||
//! \note
|
||||
//! We use struct instead of:
|
||||
//! template<template<typename...> class F, typename... Ts>
|
||||
//! using defer_ = F<Ts...>;
|
||||
@ -150,18 +178,18 @@ namespace meta{
|
||||
//! defer alias template for F<Ts...>
|
||||
template<template<class...> class F, class... Ts>
|
||||
using defer = if_<
|
||||
is_evaluable<F, Ts...>,
|
||||
detail::is_applicable_<F, Ts...>,
|
||||
detail::defer_<F, Ts...>,
|
||||
nil_
|
||||
nil_ //!< This should be identity<nil_> if nil_ was empty
|
||||
>;
|
||||
|
||||
//! defer_i alias template for F<T, Is...>
|
||||
// template <typename T, template<T...> class F, T... Is>
|
||||
// using defer_i = if_ <
|
||||
// is_evaluable_i<T, F<Is...>>,
|
||||
// detail::defer_i_<F, Is...>,
|
||||
// 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_ //!< This should be identity<nil_> if nil_ was empty
|
||||
>;
|
||||
//! @}
|
||||
|
||||
/*!
|
||||
@ -171,27 +199,35 @@ namespace meta{
|
||||
template <template <typename...> class F>
|
||||
struct quote {
|
||||
template <typename... Args>
|
||||
using apply = type_<defer<F, Args...>>; //!< defer here to avoid DR1430
|
||||
using apply = type_<
|
||||
defer<F, Args...> //!< defer here to avoid DR1430
|
||||
>;
|
||||
};
|
||||
|
||||
//! Wrap a template \p F taking literals of type \p T into an Invokable
|
||||
// template <typename T, template <T...> class F>
|
||||
// struct quote_i {
|
||||
// // requires meta::Integral
|
||||
// template <typename... Is>
|
||||
// using apply = type_<
|
||||
// defer_i<T, F, Is...> //!< defer here to avoid DR1430
|
||||
// >;
|
||||
// };
|
||||
template <typename T, template <T...> class F>
|
||||
struct quote_i {
|
||||
// requires meta::Integral
|
||||
template <typename... Ts>
|
||||
using apply = type_<
|
||||
defer_i<T, F, Ts::type::value...> //!< defer here to avoid DR1430
|
||||
>;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Invoke the nested apply metafunction from \c Fn
|
||||
* with the arguments \c Args.
|
||||
* requires Invocable(Fn)
|
||||
*/
|
||||
template <typename Fn, typename... Args>
|
||||
using invoke = typename Fn::template apply<Args...>;
|
||||
|
||||
/*!
|
||||
* Invoke the nested apply metafunction from \c Fn
|
||||
* with the arguments \c Args.
|
||||
*/
|
||||
template <typename Fn, typename... Args>
|
||||
using invoke_t = type_<invoke <Fn, Args...>>;
|
||||
|
||||
//! compose
|
||||
//! @{
|
||||
namespace detail {
|
||||
@ -214,34 +250,64 @@ namespace meta{
|
||||
using apply = invoke<Fn0, Args...>;
|
||||
};
|
||||
}
|
||||
|
||||
/*!
|
||||
* Create an invokable from other invokables by composition
|
||||
* ex:
|
||||
* compose<Fns...> will result to something like F0<F1<F2<F3<...>>>>
|
||||
* Create an invokable from other invocables by composition.
|
||||
* \note
|
||||
* This implies from N invocables in \p Fns the first N-1 has to be unary.
|
||||
* That because of the "return" type of metafunction. They can only return one
|
||||
* type. So for n-ary invocables in the N-1 places the typelist<> is the solution.
|
||||
* \example
|
||||
* \code
|
||||
* static_assert(std::is_same<
|
||||
* invoke<compose<F1, F2, F3>, int>,
|
||||
* F1 <F2 <F3 <int>>>
|
||||
* >, "" );
|
||||
* \endcode
|
||||
*/
|
||||
template <typename... Fns>
|
||||
using compose = detail::compose_<Fns...>;
|
||||
//! @}
|
||||
|
||||
//! Applies the Invocable \p Fn by binding the arguments \p Ts
|
||||
//! to the \e front of \p Fn.
|
||||
/*!
|
||||
* Applies the Invocable \p Fn by binding the arguments \p Ts
|
||||
* to the front of \p Fn.
|
||||
*/
|
||||
template<typename Fn, typename... Ts>
|
||||
struct bind_front {
|
||||
template<typename... Us>
|
||||
using apply = invoke<Fn, Ts..., Us...>;
|
||||
};
|
||||
|
||||
//! Applies the Invocable \p Fn by binding the arguments \p Ts
|
||||
//! to the \e back of \p Fn.
|
||||
/*!
|
||||
* Applies the Invocable \p Fn by binding the arguments \p Ts
|
||||
* to the back of \p Fn.
|
||||
*/
|
||||
template<typename Fn, typename... Ts>
|
||||
struct bind_back {
|
||||
template<typename... Us>
|
||||
using apply = invoke<Fn, Us..., Ts...>;
|
||||
};
|
||||
|
||||
/*
|
||||
* ========== 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_utility_h__ */
|
||||
#endif /* __utl_meta_invoke_h__ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user