// 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 #include #include #include #include #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \ defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \ defined(BOOST_TYPE_ERASURE_DOXYGEN) || \ BOOST_WORKAROUND(BOOST_MSVC, == 1800) 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, ~)); \ } \ }; \ \ } \ } /** 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) #ifdef BOOST_TYPE_ERASURE_DOXYGEN /** * \brief Defines a primitive concept for a free function. * * \param concept_name is the name of the concept to declare. * If it is omitted it defaults to has_ ## function_name * \param function_name is the name of the function. * * The declaration of the concept is * \code * template * struct concept_name; * \endcode * where Sig is a function type giving the * signature of the function. * * This macro can only be used at namespace scope. * * Example: * * \code * BOOST_TYPE_ERASURE_FREE(to_string) * typedef has_to_string to_string_concept; * \endcode * * In C++03, the macro can only be used in the global namespace and * is defined as: * * \code * #define BOOST_TYPE_ERASURE_FREE(qualified_name, function_name, N) * \endcode * * Example: * * \code * BOOST_TYPE_ERASURE_FREE((boost)(has_to_string), to_string, 1) * \endcode * * For backwards compatibility, this form is always accepted. */ #define BOOST_TYPE_ERASURE_FREE(concept_name, function_name) #else #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 #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; }; #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && \ !defined(BOOST_NO_CXX11_DECLTYPE) template using make_index_list_t = typename ::boost::type_erasure::detail::make_index_list::type; #if BOOST_WORKAROUND(BOOST_MSVC, == 1900) template struct first_placeholder_index_ : ::boost::type_erasure::detail::first_placeholder_index< ::boost::remove_cv_t< ::boost::remove_reference_t >... > {}; template using first_placeholder_index_t = typename ::boost::type_erasure::detail::first_placeholder_index_::type; #else template using first_placeholder_index_t = typename ::boost::type_erasure::detail::first_placeholder_index< ::boost::remove_cv_t< ::boost::remove_reference_t >... >::type; #endif template using free_param_t = typename ::boost::mpl::eval_if_c<(::boost::type_erasure::detail::first_placeholder_index_t::value == I), ::boost::type_erasure::detail::maybe_const_this_param, \ ::boost::type_erasure::as_param >::type; template struct free_interface_chooser { template class C, template class F> using apply = Base; }; template struct free_interface_chooser< R(A...), typename ::boost::type_erasure::detail::first_placeholder< ::boost::remove_cv_t< ::boost::remove_reference_t >...>::type> { template class C, template class F> using apply = F >; }; template class C, template class F> struct free_choose_interface { template using apply = typename free_interface_chooser::template apply; }; /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_FREE_I(concept_name, function_name) \ template \ struct concept_name; \ \ namespace boost_type_erasure_impl { \ \ template \ struct concept_name ## _free_interface; \ template \ struct concept_name ## _free_interface > : Base {\ friend ::boost::type_erasure::rebind_any_t \ function_name( \ ::boost::type_erasure::detail::free_param_t... t) \ { \ return ::boost::type_erasure::call( \ concept_name(), \ std::forward< ::boost::type_erasure::detail::free_param_t >(t)...);\ } \ }; \ \ template \ struct concept_name ## free; \ \ template \ struct concept_name ## free { \ static R apply(T... t) \ { return function_name(std::forward(t)...); } \ }; \ \ template \ struct concept_name ## free { \ static void apply(T... t) \ { function_name(std::forward(t)...); } \ }; \ \ } \ \ template \ struct concept_name : \ boost_type_erasure_impl::concept_name##free \ {}; \ \ template \ ::boost::type_erasure::detail::free_choose_interface \ boost_type_erasure_find_interface(concept_name); #define BOOST_TYPE_ERASURE_FREE_SIMPLE(name, ...) \ BOOST_TYPE_ERASURE_FREE_I(has_ ## name, name) #define BOOST_TYPE_ERASURE_FREE_NS_I(concept_name, name) \ BOOST_TYPE_ERASURE_FREE_I(concept_name, name) #define BOOST_TYPE_ERASURE_FREE_NS(concept_name, name) \ BOOST_TYPE_ERASURE_OPEN_NAMESPACE(concept_name) \ BOOST_TYPE_ERASURE_FREE_NS_I(BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(concept_name)), concept_name), name) \ BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(concept_name) #define BOOST_TYPE_ERASURE_FREE_NAMED(concept_name, name, ...) \ BOOST_PP_IF(BOOST_PP_IS_BEGIN_PARENS(concept_name), \ BOOST_TYPE_ERASURE_FREE_NS, \ BOOST_TYPE_ERASURE_FREE_I) \ (concept_name, name) #define BOOST_TYPE_ERASURE_FREE_CAT(x, y) x y #define BOOST_TYPE_ERASURE_FREE(name, ...) \ BOOST_TYPE_ERASURE_FREE_CAT( \ BOOST_PP_IF(BOOST_VMD_IS_EMPTY(__VA_ARGS__), \ BOOST_TYPE_ERASURE_FREE_SIMPLE, \ BOOST_TYPE_ERASURE_FREE_NAMED), \ (name, __VA_ARGS__)) #else /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_FREE_II(qual_name, concept_name, function_name) \ 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>\ {}; \ \ } \ } /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_FREE_I(namespace_name, concept_name, function_name) \ BOOST_TYPE_ERASURE_FREE_II(namespace_name, concept_name, function_name) #define BOOST_TYPE_ERASURE_FREE(qualified_name, function_name, ...) \ BOOST_TYPE_ERASURE_FREE_I( \ qualified_name, \ BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \ function_name) #endif } } } #endif #endif