|
|
@@ -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__ */
|