123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487 |
- // 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 <boost/detail/workaround.hpp>
- #include <boost/preprocessor/repetition/enum.hpp>
- #include <boost/preprocessor/repetition/enum_trailing.hpp>
- #include <boost/preprocessor/repetition/enum_params.hpp>
- #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
- #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
- #include <boost/preprocessor/repetition/enum_binary_params.hpp>
- #include <boost/preprocessor/cat.hpp>
- #include <boost/preprocessor/control/if.hpp>
- #include <boost/preprocessor/punctuation/is_begin_parens.hpp>
- #include <boost/vmd/is_empty.hpp>
- #include <boost/type_traits/remove_reference.hpp>
- #include <boost/type_traits/remove_cv.hpp>
- #include <boost/mpl/eval_if.hpp>
- #include <boost/mpl/identity.hpp>
- #include <boost/mpl/int.hpp>
- #include <boost/mpl/next.hpp>
- #include <boost/type_erasure/detail/macro.hpp>
- #include <boost/type_erasure/detail/const.hpp>
- #include <boost/type_erasure/config.hpp>
- #include <boost/type_erasure/derived.hpp>
- #include <boost/type_erasure/rebind_any.hpp>
- #include <boost/type_erasure/param.hpp>
- #include <boost/type_erasure/is_placeholder.hpp>
- #include <boost/type_erasure/call.hpp>
- #include <boost/type_erasure/concept_interface.hpp>
- #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<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_TYPE_ERASURE_MAX_ARITY, class T, void)>
- struct first_placeholder {
- typedef typename ::boost::mpl::eval_if<is_placeholder<T0>,
- ::boost::mpl::identity<T0>,
- first_placeholder<BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_TYPE_ERASURE_MAX_ARITY, T)>
- >::type type;
- };
- template<>
- struct first_placeholder<> {};
- template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_TYPE_ERASURE_MAX_ARITY, class T, void)>
- struct first_placeholder_index :
- ::boost::mpl::eval_if<is_placeholder<T0>,
- ::boost::mpl::int_<0>,
- ::boost::mpl::next<first_placeholder_index<BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_TYPE_ERASURE_MAX_ARITY, T)> >
- >::type
- {};
- }
- }
- }
- /** INTERNAL ONLY */
- #define BOOST_TYPE_ERASURE_FREE_QUALIFIED_ID(seq, N) \
- BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq)<R(BOOST_PP_ENUM_PARAMS(N, T))>
- /** INTERNAL ONLY */
- #define BOOST_TYPE_ERASURE_FREE_UNQUALIFIED_PARAM_TYPE(z, n, data) \
- typename ::boost::remove_cv<typename ::boost::remove_reference<BOOST_PP_CAT(T, n)>::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_PP_CAT(T, n), Base>, \
- ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(T, n)> \
- >::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)>(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<typename ::boost::mpl::eval_if_c<(_boost_type_erasure_free_p_idx::value == n), \
- ::boost::type_erasure::detail::maybe_const_this_param<BOOST_PP_CAT(T, n), Base>, \
- ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(T, n)> \
- >::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<class Sig> \
- struct concept_name; \
- \
- template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)> \
- struct concept_name<R(BOOST_PP_ENUM_PARAMS(N, T))> { \
- static R apply(BOOST_PP_ENUM_BINARY_PARAMS(N, T, t)) \
- { return function_name(BOOST_TYPE_ERASURE_FREE_FORWARD(N)); } \
- }; \
- \
- template<BOOST_PP_ENUM_PARAMS(N, class T)> \
- struct concept_name<void(BOOST_PP_ENUM_PARAMS(N, T))> { \
- 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<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T), class Base> \
- 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<Base, R>::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 <code>has_ ## function_name</code>
- * \param function_name is the name of the function.
- *
- * The declaration of the concept is
- * \code
- * template<class Sig>
- * 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<std::string(_self const&)> 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<int... N>
- struct index_list {};
- namespace detail {
-
- template<class... T>
- struct first_placeholder;
- template<class T0, class... T>
- struct first_placeholder<T0, T...> {
- typedef typename ::boost::mpl::eval_if<is_placeholder<T0>,
- ::boost::mpl::identity<T0>,
- first_placeholder<T...>
- >::type type;
- };
- template<>
- struct first_placeholder<> {};
- template<class... T>
- struct first_placeholder_index;
- template<class T0, class... T>
- struct first_placeholder_index<T0, T...> :
- ::boost::mpl::eval_if<is_placeholder<T0>,
- ::boost::mpl::int_<0>,
- ::boost::mpl::next<first_placeholder_index<T...> >
- >::type
- {};
- template<class Sig>
- struct transform_free_signature;
- template<class T, int N>
- struct push_back_index;
- template<int... N, int X>
- struct push_back_index<index_list<N...>, X>
- {
- typedef index_list<N..., X> type;
- };
- template<int N>
- struct make_index_list {
- typedef typename push_back_index<
- typename make_index_list<N-1>::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<int N>
- using make_index_list_t = typename ::boost::type_erasure::detail::make_index_list<N>::type;
- #if BOOST_WORKAROUND(BOOST_MSVC, == 1900)
- template<class... T>
- struct first_placeholder_index_ :
- ::boost::type_erasure::detail::first_placeholder_index<
- ::boost::remove_cv_t< ::boost::remove_reference_t<T> >...
- >
- {};
- template<class... T>
- using first_placeholder_index_t =
- typename ::boost::type_erasure::detail::first_placeholder_index_<T...>::type;
- #else
- template<class... T>
- using first_placeholder_index_t =
- typename ::boost::type_erasure::detail::first_placeholder_index<
- ::boost::remove_cv_t< ::boost::remove_reference_t<T> >...
- >::type;
- #endif
- template<class Base, class Tn, int I, class... T>
- using free_param_t =
- typename ::boost::mpl::eval_if_c<(::boost::type_erasure::detail::first_placeholder_index_t<T...>::value == I),
- ::boost::type_erasure::detail::maybe_const_this_param<Tn, Base>, \
- ::boost::type_erasure::as_param<Base, Tn>
- >::type;
- template<class Sig, class ID>
- struct free_interface_chooser
- {
- template<class Base, template<class> class C, template<class...> class F>
- using apply = Base;
- };
- template<class R, class... A>
- struct free_interface_chooser<
- R(A...),
- typename ::boost::type_erasure::detail::first_placeholder<
- ::boost::remove_cv_t< ::boost::remove_reference_t<A> >...>::type>
- {
- template<class Base, template<class> class C, template<class...> class F>
- using apply = F<R(A...), Base,
- ::boost::type_erasure::detail::make_index_list_t<sizeof...(A)> >;
- };
- template<class Sig, template<class> class C, template<class...> class F>
- struct free_choose_interface {
- template<class Concept, class Base, class ID>
- using apply = typename free_interface_chooser<Sig, ID>::template apply<Base, C, F>;
- };
- /** INTERNAL ONLY */
- #define BOOST_TYPE_ERASURE_FREE_I(concept_name, function_name) \
- template<class Sig> \
- struct concept_name; \
- \
- namespace boost_type_erasure_impl { \
- \
- template<class Sig, class Base, class Idx> \
- struct concept_name ## _free_interface; \
- template<class R, class... T, class Base, int... I> \
- struct concept_name ## _free_interface<R(T...), Base, ::boost::type_erasure::index_list<I...> > : Base {\
- friend ::boost::type_erasure::rebind_any_t<Base, R> \
- function_name( \
- ::boost::type_erasure::detail::free_param_t<Base, T, I, T...>... t) \
- { \
- return ::boost::type_erasure::call( \
- concept_name<R(T...)>(), \
- std::forward< ::boost::type_erasure::detail::free_param_t<Base, T, I, T...> >(t)...);\
- } \
- }; \
- \
- template<class Sig> \
- struct concept_name ## free; \
- \
- template<class R, class... T> \
- struct concept_name ## free<R(T...)> { \
- static R apply(T... t) \
- { return function_name(std::forward<T>(t)...); } \
- }; \
- \
- template<class... T> \
- struct concept_name ## free<void(T...)> { \
- static void apply(T... t) \
- { function_name(std::forward<T>(t)...); } \
- }; \
- \
- } \
- \
- template<class Sig> \
- struct concept_name : \
- boost_type_erasure_impl::concept_name##free<Sig> \
- {}; \
- \
- template<class Sig> \
- ::boost::type_erasure::detail::free_choose_interface<Sig, concept_name, \
- boost_type_erasure_impl::concept_name ## _free_interface> \
- boost_type_erasure_find_interface(concept_name<Sig>);
- #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<class Sig> \
- struct concept_name; \
- \
- template<class R, class... T> \
- struct concept_name<R(T...)> { \
- static R apply(T... t) \
- { return function_name(std::forward<T>(t)...); } \
- }; \
- \
- template<class... T> \
- struct concept_name<void(T...)> { \
- static void apply(T... t) \
- { function_name(std::forward<T>(t)...); } \
- }; \
- \
- BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qual_name) \
- \
- namespace boost { \
- namespace type_erasure { \
- \
- template<class Sig, class Base, class Idx> \
- struct inject ## concept_name; \
- template<class R, class... T, class Base, int... I> \
- struct inject ## concept_name<R(T...), Base, index_list<I...> > : Base {\
- typedef typename ::boost::type_erasure::detail::first_placeholder_index< \
- typename ::boost::remove_cv< \
- typename ::boost::remove_reference<T>::type \
- >::type... \
- >::type _boost_type_erasure_free_p_idx; \
- friend typename ::boost::type_erasure::rebind_any<Base, R>::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<T, Base>, \
- ::boost::type_erasure::as_param<Base, T> \
- >::type... t) \
- { \
- return ::boost::type_erasure::call( \
- BOOST_TYPE_ERASURE_QUALIFIED_NAME(qual_name)<R(T...)>(),\
- std::forward<typename ::boost::mpl::eval_if_c<(_boost_type_erasure_free_p_idx::value == I), \
- ::boost::type_erasure::detail::maybe_const_this_param<T, Base>, \
- ::boost::type_erasure::as_param<Base, T> \
- >::type>(t)...); \
- } \
- }; \
- \
- template<class R, class... T, class Base> \
- struct concept_interface< \
- BOOST_TYPE_ERASURE_QUALIFIED_NAME(qual_name)<R(T...)>, \
- Base, \
- typename ::boost::type_erasure::detail::first_placeholder< \
- typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type...>::type \
- > : inject ## concept_name<R(T...), Base, typename ::boost::type_erasure::detail::make_index_list<sizeof...(T)>::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
|