diff options
Diffstat (limited to 'boost/type_erasure/detail/member11.hpp')
-rw-r--r-- | boost/type_erasure/detail/member11.hpp | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/boost/type_erasure/detail/member11.hpp b/boost/type_erasure/detail/member11.hpp new file mode 100644 index 0000000000..7bc8eee6a9 --- /dev/null +++ b/boost/type_erasure/detail/member11.hpp @@ -0,0 +1,214 @@ +// Boost.TypeErasure library +// +// Copyright 2018 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_DETAIL_MEMBER11_HPP_INCLUDED +#define BOOST_TYPE_ERASURE_DETAIL_MEMBER11_HPP_INCLUDED + +#include <boost/config.hpp> + +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && \ + !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ + !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \ + !defined(BOOST_NO_CXX11_DECLTYPE) && \ + !BOOST_WORKAROUND(BOOST_MSVC, == 1800) + +#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/if.hpp> +#include <boost/type_erasure/detail/const.hpp> +#include <boost/type_erasure/detail/macro.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> + +namespace boost { +namespace type_erasure { +namespace detail { + +template<class P, template<class ...> class interface, class Sig, class Concept, class Base, class ID> +using choose_member_interface = typename ::boost::mpl::if_c< ::boost::is_reference<P>::value, + typename ::boost::mpl::if_c< ::boost::type_erasure::detail::is_non_const_ref<P>::value, + interface<Sig, Concept, Base, const ID>, + Base + >::type, + interface<Sig, Concept, Base, ID> +>::type; + + +struct dummy {}; + +template<class Sig> +struct choose_member_impl; + +template<class R, class C, class... T> +struct choose_member_impl<R (C::*)(T...) const> +{ + template<class P, template<class> class M, template<class,class> class S> + using apply = ::boost::mpl::vector1<S<R(T...), const P> >; +}; + +template<class R, class C, class... T> +struct choose_member_impl<R (C::*)(T...)> +{ + template<class P, template<class> class M, template<class,class> class S> + using apply = M<R(P&, T...)>; +}; + +template<class Sig, class P, template<class> class M, template<class, class> class Self> +using choose_member_impl_t = + typename ::boost::type_erasure::detail::choose_member_impl< + Sig (::boost::type_erasure::detail::dummy::*) + >::template apply<P, M, Self>; + +template<class Sig, class T, class ID> +struct member_interface_chooser +{ + template<class Base, template<class, class> class C, template<class...> class M> + using apply = Base; +}; + +template<class R, class T, class... A> +struct member_interface_chooser<R(A...), T, T> +{ + template<class Base, template<class, class> class C, template<class...> class M> + using apply = ::boost::type_erasure::detail::choose_member_interface< + ::boost::type_erasure::placeholder_of_t<Base>, + M, + R(A...), C<R(A...), T>, Base, T>; +}; + +template<class R, class T, class... A> +struct member_interface_chooser<R(A...), const T, T> +{ + template<class Base, template<class, class> class C, template<class...> class M> + using apply = M<R(A...), C<R(A...), const T>, Base, const T>; +}; + +template<class Sig, class T, template<class, class> class C, template<class...> class M> +struct member_choose_interface +{ + template<class Concept, class Base, class ID> + using apply = typename ::boost::type_erasure::detail::member_interface_chooser<Sig, T, ID>::template apply<Base, C, M>; +}; + +} +} +} + +#define BOOST_TYPE_ERASURE_MEMBER_I(concept_name, function_name) \ +template<class Sig, class T = ::boost::type_erasure::_self> \ +struct concept_name; \ + \ +namespace boost_type_erasure_impl { \ + \ +template<class Sig, class T> \ +using concept_name ## self = concept_name<Sig, T>; \ + \ +template<class Sig, class Concept, class Base, class ID, class Enable = void>\ +struct concept_name ## _member_interface; \ + \ +template<class R, class... A, class Concept, class Base, class ID, class V> \ +struct concept_name ## _member_interface<R(A...), Concept, Base, ID, V> : Base\ +{ \ + typedef void _boost_type_erasure_has_member ## function_name; \ + ::boost::type_erasure::rebind_any_t<Base, R> function_name(::boost::type_erasure::as_param_t<Base, A>... a)\ + { return ::boost::type_erasure::call(Concept(), *this, std::forward<A>(a)...); }\ +}; \ + \ +template<class R, class... A, class Concept, class Base, class ID> \ +struct concept_name ## _member_interface<R(A...), Concept, Base, ID, \ + typename Base::_boost_type_erasure_has_member ## function_name> : Base \ +{ \ + using Base::function_name; \ + ::boost::type_erasure::rebind_any_t<Base, R> function_name(::boost::type_erasure::as_param_t<Base, A>... a)\ + { return ::boost::type_erasure::call(Concept(), *this, std::forward<A>(a)...); }\ +}; \ + \ +template<class R, class... A, class Concept, class Base, class ID, class V> \ +struct concept_name ## _member_interface<R(A...), Concept, Base, const ID, V> : Base\ +{ \ + typedef void _boost_type_erasure_has_member ## function_name; \ + ::boost::type_erasure::rebind_any_t<Base, R> function_name(::boost::type_erasure::as_param_t<Base, A>... a) const\ + { return ::boost::type_erasure::call(Concept(), *this, std::forward<A>(a)...); }\ +}; \ + \ +template<class R, class... A, class Concept, class Base, class ID> \ +struct concept_name ## _member_interface<R(A...), Concept, Base, const ID, \ + typename Base::_boost_type_erasure_has_member ## function_name> : Base \ +{ \ + using Base::function_name; \ + ::boost::type_erasure::rebind_any_t<Base, R> function_name(::boost::type_erasure::as_param_t<Base, A>... a) const\ + { return ::boost::type_erasure::call(Concept(), *this, std::forward<A>(a)...); }\ +}; \ + \ +template<class Sig> \ +struct concept_name ## member; \ + \ +template<class R, class T0, class... T> \ +struct concept_name ## member<R(T0, T...)> { \ + static R apply(T0 t0, T... t) \ + { return t0.function_name(std::forward<T>(t)...); } \ +}; \ + \ +template<class T0, class... T> \ +struct concept_name ## member<void(T0, T...)> { \ + static void apply(T0 t0, T... t) \ + { t0.function_name(std::forward<T>(t)...); } \ +}; \ + \ +} \ + \ +template<class Sig, class T> \ +struct concept_name : \ + ::boost::type_erasure::detail::choose_member_impl_t<Sig, T, \ + boost_type_erasure_impl::concept_name##member, \ + boost_type_erasure_impl::concept_name##self \ + > \ +{}; \ + \ +template<class Sig, class T> \ +::boost::type_erasure::detail::member_choose_interface<Sig, T, concept_name,\ + boost_type_erasure_impl::concept_name ## _member_interface> \ +boost_type_erasure_find_interface(concept_name<Sig, T>); + +#define BOOST_TYPE_ERASURE_MEMBER_SIMPLE(name, ...) \ + BOOST_TYPE_ERASURE_MEMBER_I(has_ ## name, name) + +#define BOOST_TYPE_ERASURE_MEMBER_NS_I(concept_name, name) \ + BOOST_TYPE_ERASURE_MEMBER_I(concept_name, name) + +#define BOOST_TYPE_ERASURE_MEMBER_NS(concept_name, name) \ + BOOST_TYPE_ERASURE_OPEN_NAMESPACE(concept_name) \ + BOOST_TYPE_ERASURE_MEMBER_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_MEMBER_NAMED(concept_name, name, ...) \ + BOOST_PP_IF(BOOST_PP_IS_BEGIN_PARENS(concept_name), \ + BOOST_TYPE_ERASURE_MEMBER_NS, \ + BOOST_TYPE_ERASURE_MEMBER_I) \ + (concept_name, name) + +#define BOOST_TYPE_ERASURE_MEMBER_CAT(x, y) x y + +#define BOOST_TYPE_ERASURE_MEMBER(name, ...) \ + BOOST_TYPE_ERASURE_MEMBER_CAT( \ + BOOST_PP_IF(BOOST_VMD_IS_EMPTY(__VA_ARGS__), \ + BOOST_TYPE_ERASURE_MEMBER_SIMPLE, \ + BOOST_TYPE_ERASURE_MEMBER_NAMED), \ + (name, __VA_ARGS__)) + +#endif + +#endif |