2 // Contains multivisitors that are implemented via variadic templates and std::tuple
4 // See http://www.boost.org for most recent version, including documentation.
6 // Copyright Antony Polukhin, 2013-2014.
8 // Distributed under the Boost
9 // Software License, Version 1.0. (See accompanying file
10 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
12 #ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
13 #define BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
19 #include <boost/variant/detail/apply_visitor_unary.hpp>
20 #include <boost/variant/variant_fwd.hpp> // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
22 #if defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_HDR_TUPLE)
23 # error "This file requires <tuple> and variadic templates support"
30 namespace detail { namespace variant {
32 // Implementing some of the C++14 features in C++11
33 template <std::size_t... I> class index_sequence {};
35 template <std::size_t N, std::size_t... I>
36 struct make_index_sequence
37 : make_index_sequence<N-1, N-1, I...>
39 template <std::size_t... I>
40 struct make_index_sequence<0, I...>
41 : index_sequence<I...>
44 template <class... Types>
45 std::tuple<Types&...> forward_as_tuple_simple(Types&... args) BOOST_NOEXCEPT
47 return std::tuple<Types&...>(args...);
50 // Implementing some of the helper tuple methods
51 template <std::size_t... I, typename Tuple>
52 std::tuple<typename std::tuple_element<I + 1, Tuple>::type...>
53 tuple_tail_impl(const Tuple& tpl, index_sequence<I...>)
56 typename std::tuple_element<I + 1, Tuple>::type...
57 > (std::get<I + 1>(tpl)...);
60 template <typename Head, typename... Tail>
61 std::tuple<Tail...> tuple_tail(const std::tuple<Head, Tail...>& tpl)
63 return tuple_tail_impl(tpl, make_index_sequence<sizeof...(Tail)>());
68 // Forward declaration
69 template <typename Visitor, typename Visitables, typename... Values>
70 class one_by_one_visitor_and_value_referer;
72 template <typename Visitor, typename Visitables, typename... Values>
73 inline one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... >
74 make_one_by_one_visitor_and_value_referer(
75 Visitor& visitor, Visitables visitables, std::tuple<Values&...> values
78 return one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... > (
79 visitor, visitables, values
83 template <typename Visitor, typename Visitables, typename... Values>
84 class one_by_one_visitor_and_value_referer
87 std::tuple<Values&...> values_;
88 Visitables visitables_;
91 one_by_one_visitor_and_value_referer(
92 Visitor& visitor, Visitables visitables, std::tuple<Values&...> values
96 , visitables_(visitables)
99 public: // visitor interfaces
100 typedef typename Visitor::result_type result_type;
102 template <typename Value>
103 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) operator()(Value& value) const
105 return ::boost::apply_visitor(
106 make_one_by_one_visitor_and_value_referer(
108 tuple_tail(visitables_),
109 std::tuple_cat(values_, std::tuple<Value&>(value))
111 , std::get<0>(visitables_) // getting Head element
116 one_by_one_visitor_and_value_referer& operator=(const one_by_one_visitor_and_value_referer&);
119 template <typename Visitor, typename... Values>
120 class one_by_one_visitor_and_value_referer<Visitor, std::tuple<>, Values...>
123 std::tuple<Values&...> values_;
126 one_by_one_visitor_and_value_referer(
127 Visitor& visitor, std::tuple<> /*visitables*/, std::tuple<Values&...> values
133 typedef typename Visitor::result_type result_type;
135 template <class Tuple, std::size_t... I>
136 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) do_call(Tuple t, index_sequence<I...>) const {
137 return visitor_(std::get<I>(t)...);
140 template <typename Value>
141 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) operator()(Value& value) const
144 std::tuple_cat(values_, std::tuple<Value&>(value)),
145 make_index_sequence<sizeof...(Values) + 1>()
150 }} // namespace detail::variant
152 template <class Visitor, class T1, class T2, class T3, class... TN>
153 inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
154 apply_visitor(const Visitor& visitor, T1& v1, T2& v2, T3& v3, TN&... vn)
156 return ::boost::apply_visitor(
157 ::boost::detail::variant::make_one_by_one_visitor_and_value_referer(
159 ::boost::detail::variant::forward_as_tuple_simple(v2, v3, vn...),
166 template <class Visitor, class T1, class T2, class T3, class... TN>
167 inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
168 apply_visitor(Visitor& visitor, T1& v1, T2& v2, T3& v3, TN&... vn)
170 return ::boost::apply_visitor(
171 ::boost::detail::variant::make_one_by_one_visitor_and_value_referer(
173 ::boost::detail::variant::forward_as_tuple_simple(v2, v3, vn...),
182 #endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP