/*! * \file utl/meta/invoke.h * \brief Template meta-programming utilities for callables */ #ifndef __utl_meta_invoke_h__ #define __utl_meta_invoke_h__ #include #include #include /*! * \ingroup meta * \defgroup meta_invoke Invoke * A meta-programming invoke() analogous. * * This module provides higher order tools to meta. utl::meta's metafunctions inputs are types. * The metafunctions though are templates in the form of `template class`. * So we can not pass metafunctions to other metafunctions. The utl::meta provides tools to wrap metafunctions * in a type. This way we create the concepts of: * * - \c invocable which is a type containing a metafunction inside. * - \c evaluation which is the way of unwrapping the metafunction inside the invocable type. * * In order to accomplish that, by convention, a \c meta::invocable shall contain a nested * template type named \c apply which is bind to actual invocable meta-function. Then we can: * * - Use \c wrap<> or even better \c quote<> in order to wrap a metafunction to a type (metafunction class) * - Pass these wrapped types to other metafunctions * - \c invoke<> the inner \c apply from a wrapped metafunction class. */ //! @{ namespace utl { namespace meta{ /*! * \name identity implementation */ //! @{ //! Identity is a metafunction always return the input type template struct identity { #if defined (UTL_WORKAROUND_CWG_1558) // redirect unused Ts... via void_t template using apply = first_of>; //!< identity is invokable, must also have apply #else template using apply = Tp; //!< identity is invokable, must also have apply #endif using type = Tp; //!< identity }; //! identity type alias template using identity_t = eval>; //! @} /*! * \name invoke, invoke_t */ //! @{ /*! * Invoke the nested apply meta-function from \c Fn with the arguments \c Args. * \note * This is an analogous to the std::invoke() */ template using invoke = typename Fn::template apply; /*! * Evaluate the invocation of the nested apply metafunction from \p Fn * with the arguments \p Args. */ template using invoke_t = eval< invoke >; //! @} //! \name wrap //! @{ /*! * \brief * Wraps an n-ary Metafunction \c F to a Metafunction Class * * wrap is a higher-order primitive that wraps an n-ary Metafunction * to create a corresponding Metafunction Class (Invocable). This way * we can pass Metafunctions as types to other metafunctions and let * them \c invoke the inner templated apply. * * \tparam F The metafunction to wrap */ template