/*! * \file invoke.h * \brief Template meta-programming utilities for callables * * Copyright (C) 2018 Christos Choutouridis * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more detail. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef __utl_meta_invoke_h__ #define __utl_meta_invoke_h__ #include #include #include #include #include /*! * \ingroup meta * \defgroup invoke * */ //! @{ namespace utl { namespace meta{ /*! * \name meta:: invoke * * A meta-programming invoke() analogous. A meta:: `invocable` shall contain a nested * template type named `apply` which is bind to actual invocable meta-function. */ //! @{ /*! * *invocable* identity, identity_t. */ //! @{ template struct identity { #if defined (UTL_WORKAROUND_CWG_1558) // redirect unused Ts... via void_t template 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 using type = _Tp; //!< identity }; //! identity type alias template using identity_t = eval>; //! @} //! Is applicable trait //! @{ namespace detail { template class F, typename... T> struct is_applicable_ { template class G, typename = G> static true_ check (int); //< T.. can be passed to G template class> static false_ check (...); //< all other combinations 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_applicable_t = eval< 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 = eval < // Extra check for quoted metafunctions to check return type if_ < not_same_< eval >, 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 = eval< detail::is_applicable_i_ >; //! @} //! defer //! @{ namespace detail { //! @{ template class F, typename... Ts> struct defer_ { 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; //! //! The use of struct here is due to Core issue 1430 [1] and is used //! as suggested by Roy Crihfield in [2]. //! In short, this is due to language's inability to expand Ts... into //! a fixed parameter list of an alias template. //! //! [1]: https://wg21.link/cwg1430 //! [2]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59498 //! @} } //! defer alias template for F template class F, class... Ts> using defer = if_< detail::is_applicable_, detail::defer_, nil_ //!< This should be identity if nil_ was empty >; //! defer_i alias template for F 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 >; //! @} /*! * quote is a higher-order primitive that wraps an n-ary Metafunction * to create a corresponding Metafunction Class (Invocable). */ template