// Boost.TypeErasure library // // Copyright 2012 Steven Watanabe // // Distributed under the Boost Software License Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // $Id$ #ifndef BOOST_TYPE_ERASURE_FREE_HPP_INCLUDED #define BOOST_TYPE_ERASURE_FREE_HPP_INCLUDED #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_TYPE_ERASURE_DOXYGEN) namespace boost { namespace type_erasure { namespace detail { template struct first_placeholder { typedef typename ::boost::mpl::eval_if, ::boost::mpl::identity, first_placeholder >::type type; }; template<> struct first_placeholder<> {}; template struct first_placeholder_index : ::boost::mpl::eval_if, ::boost::mpl::int_<0>, ::boost::mpl::next > >::type {}; } } } /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_FREE_QUALIFIED_ID(seq, N) \ BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq) /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_FREE_UNQUALIFIED_PARAM_TYPE(z, n, data) \ typename ::boost::remove_cv::type>::type /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_FREE_PARAM_TYPE(z, n, data) \ typename ::boost::mpl::eval_if_c<(_boost_type_erasure_free_p_idx::value == n), \ ::boost::type_erasure::detail::maybe_const_this_param, \ ::boost::type_erasure::as_param \ >::type BOOST_PP_CAT(t, n) #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_FREE_FORWARD_I(z, n, data) ::std::forward(BOOST_PP_CAT(t, n)) /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_FREE_FORWARD(n) BOOST_PP_ENUM(n, BOOST_TYPE_ERASURE_FREE_FORWARD_I, ~) /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_FREE_FORWARD_PARAM_I(z, n, data) \ ::std::forward, \ ::boost::type_erasure::as_param \ >::type>(BOOST_PP_CAT(t, n)) #else #define BOOST_TYPE_ERASURE_FREE_FORWARD(n) BOOST_PP_ENUM_PARAMS(n, t) #define BOOST_TYPE_ERASURE_FREE_FORWARD_PARAM_I(z, n, data) BOOST_PP_CAT(t, n) #endif /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_FREE_II(qual_name, concept_name, function_name, N) \ BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qual_name) \ \ template \ struct concept_name; \ \ template \ struct concept_name { \ static R apply(BOOST_PP_ENUM_BINARY_PARAMS(N, T, t)) \ { return function_name(BOOST_TYPE_ERASURE_FREE_FORWARD(N)); } \ }; \ \ template \ struct concept_name { \ static void apply(BOOST_PP_ENUM_BINARY_PARAMS(N, T, t)) \ { function_name(BOOST_TYPE_ERASURE_FREE_FORWARD(N)); } \ }; \ \ BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qual_name) \ \ namespace boost { \ namespace type_erasure { \ \ template \ struct concept_interface< \ BOOST_TYPE_ERASURE_FREE_QUALIFIED_ID(qual_name, N), \ Base, \ typename ::boost::type_erasure::detail::first_placeholder< \ BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_FREE_UNQUALIFIED_PARAM_TYPE, ~)>::type \ > : Base { \ typedef typename ::boost::type_erasure::detail::first_placeholder_index< \ BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_FREE_UNQUALIFIED_PARAM_TYPE, ~)>::type \ _boost_type_erasure_free_p_idx; \ friend typename ::boost::type_erasure::rebind_any::type function_name( \ BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_FREE_PARAM_TYPE, ~)) \ { \ return ::boost::type_erasure::call( \ BOOST_TYPE_ERASURE_FREE_QUALIFIED_ID(qual_name, N)() \ BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FREE_FORWARD_PARAM_I, ~)); \ } \ }; \ \ } \ } #else namespace boost { namespace type_erasure { template struct index_list {}; namespace detail { template struct first_placeholder; template struct first_placeholder { typedef typename ::boost::mpl::eval_if, ::boost::mpl::identity, first_placeholder >::type type; }; template<> struct first_placeholder<> {}; template struct first_placeholder_index; template struct first_placeholder_index : ::boost::mpl::eval_if, ::boost::mpl::int_<0>, ::boost::mpl::next > >::type {}; template struct transform_free_signature; template struct push_back_index; template struct push_back_index, X> { typedef index_list type; }; template struct make_index_list { typedef typename push_back_index< typename make_index_list::type, N-1 >::type type; }; template<> struct make_index_list<0> { typedef index_list<> type; }; } } } /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_FREE_II(qual_name, concept_name, function_name, N) \ BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qual_name) \ \ template \ struct concept_name; \ \ template \ struct concept_name { \ static R apply(T... t) \ { return function_name(std::forward(t)...); } \ }; \ \ template \ struct concept_name { \ static void apply(T... t) \ { function_name(std::forward(t)...); } \ }; \ \ BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qual_name) \ \ namespace boost { \ namespace type_erasure { \ \ template \ struct inject ## concept_name; \ template \ struct inject ## concept_name > : Base {\ typedef typename ::boost::type_erasure::detail::first_placeholder_index< \ typename ::boost::remove_cv< \ typename ::boost::remove_reference::type \ >::type... \ >::type _boost_type_erasure_free_p_idx; \ friend typename ::boost::type_erasure::rebind_any::type\ function_name( \ typename ::boost::mpl::eval_if_c<(_boost_type_erasure_free_p_idx::value == I), \ ::boost::type_erasure::detail::maybe_const_this_param, \ ::boost::type_erasure::as_param \ >::type... t) \ { \ return ::boost::type_erasure::call( \ BOOST_TYPE_ERASURE_QUALIFIED_NAME(qual_name)(),\ std::forward, \ ::boost::type_erasure::as_param \ >::type>(t)...); \ } \ }; \ \ template \ struct concept_interface< \ BOOST_TYPE_ERASURE_QUALIFIED_NAME(qual_name), \ Base, \ typename ::boost::type_erasure::detail::first_placeholder< \ typename ::boost::remove_cv::type>::type...>::type \ > : inject ## concept_name::type>\ {}; \ \ } \ } #endif /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_FREE_I(namespace_name, concept_name, function_name, N)\ BOOST_TYPE_ERASURE_FREE_II(namespace_name, concept_name, function_name, N) /** * \brief Defines a primitive concept for a free function. * * \param qualified_name should be a preprocessor sequence * of the form (namespace1)(namespace2)...(concept_name). * \param function_name is the name of the function. * \param N is the number of arguments of the function. * * The declaration of the concept is * \code * template * struct ::namespace1::namespace2::...::concept_name; * \endcode * where Sig is a function type giving the * signature of the function. * * This macro can only be used in the global namespace. * * Example: * * \code * BOOST_TYPE_ERASURE_FREE((boost)(has_to_string), to_string, 1) * \endcode */ #define BOOST_TYPE_ERASURE_FREE(qualified_name, function_name, N) \ BOOST_TYPE_ERASURE_FREE_I( \ qualified_name, \ BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \ function_name, \ N) #endif