123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- // Boost.Varaint
- // Contains multivisitors that are implemented via variadic templates and std::tuple
- //
- // See http://www.boost.org for most recent version, including documentation.
- //
- // Copyright Antony Polukhin, 2013-2024.
- //
- // 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).
- #ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
- #define BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
- #if defined(_MSC_VER)
- # pragma once
- #endif
- #include <boost/variant/detail/apply_visitor_unary.hpp>
- #include <boost/variant/variant_fwd.hpp>
- #include <boost/type_traits/is_lvalue_reference.hpp>
- #include <boost/core/enable_if.hpp>
- #include <tuple>
- namespace boost {
- namespace detail { namespace variant {
- // Implementing some of the C++14 features in C++11
- template <std::size_t... I> class index_sequence {};
- template <std::size_t N, std::size_t... I>
- struct make_index_sequence
- : make_index_sequence<N-1, N-1, I...>
- {};
- template <std::size_t... I>
- struct make_index_sequence<0, I...>
- : index_sequence<I...>
- {};
- template <typename T_, bool MoveSemantics_>
- struct MoveableWrapper //Just a reference with some metadata
- {
- typedef T_ T;
- static constexpr bool MoveSemantics = MoveSemantics_;
- T& v;
- };
- template <typename Tp, bool MoveSemantics>
- MoveableWrapper<Tp, MoveSemantics>
- wrap(Tp& t)
- {
- return MoveableWrapper<Tp, MoveSemantics>{t};
- }
- template <typename Wrapper>
- typename enable_if_c<Wrapper::MoveSemantics, typename Wrapper::T>::type
- unwrap(Wrapper& w)
- {
- return std::move(w.v);
- }
- template <typename Wrapper>
- typename disable_if_c<Wrapper::MoveSemantics, typename Wrapper::T>::type &
- unwrap(Wrapper& w)
- {
- return w.v;
- }
- // Implementing some of the helper tuple methods
- template <std::size_t... I, typename Tuple>
- std::tuple<typename std::tuple_element<I + 1, Tuple>::type...>
- tuple_tail_impl(const Tuple& tpl, index_sequence<I...>)
- {
- return std::tuple<
- typename std::tuple_element<I + 1, Tuple>::type...
- > (std::get<I + 1>(tpl)...);
- }
- template <typename Head, typename... Tail>
- std::tuple<Tail...> tuple_tail(const std::tuple<Head, Tail...>& tpl)
- {
- return tuple_tail_impl(tpl, make_index_sequence<sizeof...(Tail)>());
- }
- // Forward declaration
- template <typename Visitor, typename Visitables, typename... Values>
- class one_by_one_visitor_and_value_referer;
- template <typename Visitor, typename Visitables, typename... Values>
- inline one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... >
- make_one_by_one_visitor_and_value_referer(
- Visitor& visitor, Visitables visitables, std::tuple<Values...> values
- )
- {
- return one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... > (
- visitor, visitables, values
- );
- }
- template <typename Visitor, typename Visitables, typename... Values>
- class one_by_one_visitor_and_value_referer
- {
- Visitor& visitor_;
- std::tuple<Values...> values_;
- Visitables visitables_;
- public: // structors
- one_by_one_visitor_and_value_referer(
- Visitor& visitor, Visitables visitables, std::tuple<Values...> values
- ) BOOST_NOEXCEPT
- : visitor_(visitor)
- , values_(values)
- , visitables_(visitables)
- {}
- public: // visitor interfaces
- typedef typename Visitor::result_type result_type;
- template <typename Value>
- result_type operator()(Value&& value) const
- {
- return ::boost::apply_visitor(
- make_one_by_one_visitor_and_value_referer(
- visitor_,
- tuple_tail(visitables_),
- std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value)))
- )
- , unwrap(std::get<0>(visitables_)) // getting Head element
- );
- }
- private:
- one_by_one_visitor_and_value_referer& operator=(const one_by_one_visitor_and_value_referer&);
- };
- template <typename Visitor, typename... Values>
- class one_by_one_visitor_and_value_referer<Visitor, std::tuple<>, Values...>
- {
- Visitor& visitor_;
- std::tuple<Values...> values_;
- public:
- one_by_one_visitor_and_value_referer(
- Visitor& visitor, std::tuple<> /*visitables*/, std::tuple<Values...> values
- ) BOOST_NOEXCEPT
- : visitor_(visitor)
- , values_(values)
- {}
- typedef typename Visitor::result_type result_type;
- template <class Tuple, std::size_t... I>
- result_type do_call(Tuple t, index_sequence<I...>) const {
- return visitor_(unwrap(std::get<I>(t))...);
- }
- template <typename Value>
- result_type operator()(Value&& value) const
- {
- return do_call(
- std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value))),
- make_index_sequence<sizeof...(Values) + 1>()
- );
- }
- };
- }} // namespace detail::variant
- template <class Visitor, class T1, class T2, class T3, class... TN>
- inline typename Visitor::result_type
- apply_visitor(const Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn)
- {
- return ::boost::apply_visitor(
- ::boost::detail::variant::make_one_by_one_visitor_and_value_referer(
- visitor,
- std::make_tuple(
- ::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
- ::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
- ::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
- ),
- std::tuple<>()
- ),
- std::forward<T1>(v1)
- );
- }
-
- template <class Visitor, class T1, class T2, class T3, class... TN>
- inline typename Visitor::result_type
- apply_visitor(Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn)
- {
- return ::boost::apply_visitor(
- ::boost::detail::variant::make_one_by_one_visitor_and_value_referer(
- visitor,
- std::make_tuple(
- ::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
- ::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
- ::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
- ),
- std::tuple<>()
- ),
- std::forward<T1>(v1)
- );
- }
- } // namespace boost
- #endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
|