diff --git a/include/utl/meta/invoke.h b/include/utl/meta/invoke.h index 71da809..3d87f0b 100644 --- a/include/utl/meta/invoke.h +++ b/include/utl/meta/invoke.h @@ -66,14 +66,13 @@ namespace meta{ template 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 - using _dummy = void_t; - using apply = _Tp; //!< identity is invokable, must also have apply + using apply = first_of<_Tp, void_t>; //!< identity is invokable, must also have apply #else template 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_>; //! @} - //! Is evaluable trait + //! Is applicable trait //! @{ namespace detail { - // we check for template \p F to be a metafunction with parameters \p T template class F, typename... T> - struct is_evaluable_ { + struct is_applicable_ { template class G, typename = G> - static true_ check (int); + static true_ check (int); //< T.. can be passed to G template class> - static false_ check (...); + static false_ check (...); //< all other combinations using type = decltype(check(0)); }; - // we check for template \p F with integral constant parameters \p Is of type \p T -// template class F, T... Is> -// struct is_evaluable_i_ { -// template class G, class = G> -// static true_ check (int); -// template class> -// static false_ check (...); -// -// using type = decltype(check(0)); -// }; + template + using use_ = typename Fn::template apply; + + template + struct is_applicable_q_ { + template>> + static Ret check (int); //< T.. can be passed to G + template + static nil_ check (...); //< all other combinations + + using type = decltype(check(0)); + }; + + template class F, T... Is> + struct is_applicable_i_ { + template class G, typename =G> + static true_ check (int); //< Is... can be passed to G + template class G> + static false_ check (...); //< all other combinations + + using type = decltype(check(0)); + }; } + //! check if we can instantiate \p F with parameters \p T template class F, typename... T> - using is_evaluable = type_< - detail::is_evaluable_ + using is_applicable_t = type_< + detail::is_applicable_ + >; + //! check if we can instantiate \p Q with parameters \p T and the instant + //! is different from \c nil_ + template + using is_applicable_qt = type_ < + // Extra check for quoted metafunctions to check return type + if_ < + not_same_< + type_ >, + nil_ + >, + true_, + false_ + > + >; + //! check if we can instantiate \p F with parameters \p Is of type \p T + template class F, T... Is> + using is_applicable_it = type_< + detail::is_applicable_i_ >; - -// template class F, T... Is> -// using is_evaluable_i = type_>>; //! @} @@ -128,11 +155,12 @@ namespace meta{ using type = F; }; -// template class F, T... Is> -// struct defer_i_ { -// using type = F; -// }; - //! + template class F, T... Is> + struct defer_i_ { + using type = F; + }; + + //! \note //! We use struct instead of: //! template class F, typename... Ts> //! using defer_ = F; @@ -150,18 +178,18 @@ namespace meta{ //! defer alias template for F template class F, class... Ts> using defer = if_< - is_evaluable, + detail::is_applicable_, detail::defer_, - nil_ + nil_ //!< This should be identity if nil_ was empty >; //! defer_i alias template for F -// template class F, T... Is> -// using defer_i = if_ < -// is_evaluable_i>, -// detail::defer_i_, -// nil_ -// >; + template class F, T... Is> + using defer_i = if_ < + detail::is_applicable_i_, + detail::defer_i_, + nil_ //!< This should be identity if nil_ was empty + >; //! @} /*! @@ -171,27 +199,35 @@ namespace meta{ template