Chris@102
|
1 // Boost.Varaint
|
Chris@102
|
2 // Contains multivisitors that are implemented via variadic templates and std::tuple
|
Chris@102
|
3 //
|
Chris@102
|
4 // See http://www.boost.org for most recent version, including documentation.
|
Chris@102
|
5 //
|
Chris@102
|
6 // Copyright Antony Polukhin, 2013-2014.
|
Chris@102
|
7 //
|
Chris@102
|
8 // Distributed under the Boost
|
Chris@102
|
9 // Software License, Version 1.0. (See accompanying file
|
Chris@102
|
10 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
|
Chris@102
|
11
|
Chris@102
|
12 #ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
|
Chris@102
|
13 #define BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
|
Chris@102
|
14
|
Chris@102
|
15 #if defined(_MSC_VER)
|
Chris@102
|
16 # pragma once
|
Chris@102
|
17 #endif
|
Chris@102
|
18
|
Chris@102
|
19 #include <boost/variant/detail/apply_visitor_unary.hpp>
|
Chris@102
|
20 #include "boost/variant/variant_fwd.hpp" // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
|
Chris@102
|
21
|
Chris@102
|
22 #if defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_HDR_TUPLE)
|
Chris@102
|
23 # error "This file requires <tuple> and variadic templates support"
|
Chris@102
|
24 #endif
|
Chris@102
|
25
|
Chris@102
|
26 #include <tuple>
|
Chris@102
|
27
|
Chris@102
|
28 namespace boost {
|
Chris@102
|
29
|
Chris@102
|
30 namespace detail { namespace variant {
|
Chris@102
|
31
|
Chris@102
|
32 // Implementing some of the C++14 features in C++11
|
Chris@102
|
33 template <std::size_t... I> class index_sequence {};
|
Chris@102
|
34
|
Chris@102
|
35 template <std::size_t N, std::size_t... I>
|
Chris@102
|
36 struct make_index_sequence
|
Chris@102
|
37 : make_index_sequence<N-1, N-1, I...>
|
Chris@102
|
38 {};
|
Chris@102
|
39 template <std::size_t... I>
|
Chris@102
|
40 struct make_index_sequence<0, I...>
|
Chris@102
|
41 : index_sequence<I...>
|
Chris@102
|
42 {};
|
Chris@102
|
43
|
Chris@102
|
44 template <class... Types>
|
Chris@102
|
45 std::tuple<Types&...> forward_as_tuple_simple(Types&... args) BOOST_NOEXCEPT
|
Chris@102
|
46 {
|
Chris@102
|
47 return std::tuple<Types&...>(args...);
|
Chris@102
|
48 }
|
Chris@102
|
49
|
Chris@102
|
50 // Implementing some of the helper tuple methods
|
Chris@102
|
51 template <std::size_t... I, typename Tuple>
|
Chris@102
|
52 std::tuple<typename std::tuple_element<I + 1, Tuple>::type...>
|
Chris@102
|
53 tuple_tail_impl(const Tuple& tpl, index_sequence<I...>)
|
Chris@102
|
54 {
|
Chris@102
|
55 return std::tuple<
|
Chris@102
|
56 typename std::tuple_element<I + 1, Tuple>::type...
|
Chris@102
|
57 > (std::get<I + 1>(tpl)...);
|
Chris@102
|
58 }
|
Chris@102
|
59
|
Chris@102
|
60 template <typename Head, typename... Tail>
|
Chris@102
|
61 std::tuple<Tail...> tuple_tail(const std::tuple<Head, Tail...>& tpl)
|
Chris@102
|
62 {
|
Chris@102
|
63 return tuple_tail_impl(tpl, make_index_sequence<sizeof...(Tail)>());
|
Chris@102
|
64 }
|
Chris@102
|
65
|
Chris@102
|
66
|
Chris@102
|
67
|
Chris@102
|
68 // Forward declaration
|
Chris@102
|
69 template <typename Visitor, typename Visitables, typename... Values>
|
Chris@102
|
70 class one_by_one_visitor_and_value_referer;
|
Chris@102
|
71
|
Chris@102
|
72 template <typename Visitor, typename Visitables, typename... Values>
|
Chris@102
|
73 inline one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... >
|
Chris@102
|
74 make_one_by_one_visitor_and_value_referer(
|
Chris@102
|
75 Visitor& visitor, Visitables visitables, std::tuple<Values&...> values
|
Chris@102
|
76 )
|
Chris@102
|
77 {
|
Chris@102
|
78 return one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... > (
|
Chris@102
|
79 visitor, visitables, values
|
Chris@102
|
80 );
|
Chris@102
|
81 }
|
Chris@102
|
82
|
Chris@102
|
83 template <typename Visitor, typename Visitables, typename... Values>
|
Chris@102
|
84 class one_by_one_visitor_and_value_referer
|
Chris@102
|
85 {
|
Chris@102
|
86 Visitor& visitor_;
|
Chris@102
|
87 std::tuple<Values&...> values_;
|
Chris@102
|
88 Visitables visitables_;
|
Chris@102
|
89
|
Chris@102
|
90 public: // structors
|
Chris@102
|
91 one_by_one_visitor_and_value_referer(
|
Chris@102
|
92 Visitor& visitor, Visitables visitables, std::tuple<Values&...> values
|
Chris@102
|
93 ) BOOST_NOEXCEPT
|
Chris@102
|
94 : visitor_(visitor)
|
Chris@102
|
95 , values_(values)
|
Chris@102
|
96 , visitables_(visitables)
|
Chris@102
|
97 {}
|
Chris@102
|
98
|
Chris@102
|
99 public: // visitor interfaces
|
Chris@102
|
100 typedef typename Visitor::result_type result_type;
|
Chris@102
|
101
|
Chris@102
|
102 template <typename Value>
|
Chris@102
|
103 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) operator()(Value& value) const
|
Chris@102
|
104 {
|
Chris@102
|
105 return ::boost::apply_visitor(
|
Chris@102
|
106 make_one_by_one_visitor_and_value_referer(
|
Chris@102
|
107 visitor_,
|
Chris@102
|
108 tuple_tail(visitables_),
|
Chris@102
|
109 std::tuple_cat(values_, std::tuple<Value&>(value))
|
Chris@102
|
110 )
|
Chris@102
|
111 , std::get<0>(visitables_) // getting Head element
|
Chris@102
|
112 );
|
Chris@102
|
113 }
|
Chris@102
|
114
|
Chris@102
|
115 private:
|
Chris@102
|
116 one_by_one_visitor_and_value_referer& operator=(const one_by_one_visitor_and_value_referer&);
|
Chris@102
|
117 };
|
Chris@102
|
118
|
Chris@102
|
119 template <typename Visitor, typename... Values>
|
Chris@102
|
120 class one_by_one_visitor_and_value_referer<Visitor, std::tuple<>, Values...>
|
Chris@102
|
121 {
|
Chris@102
|
122 Visitor& visitor_;
|
Chris@102
|
123 std::tuple<Values&...> values_;
|
Chris@102
|
124
|
Chris@102
|
125 public:
|
Chris@102
|
126 one_by_one_visitor_and_value_referer(
|
Chris@102
|
127 Visitor& visitor, std::tuple<> /*visitables*/, std::tuple<Values&...> values
|
Chris@102
|
128 ) BOOST_NOEXCEPT
|
Chris@102
|
129 : visitor_(visitor)
|
Chris@102
|
130 , values_(values)
|
Chris@102
|
131 {}
|
Chris@102
|
132
|
Chris@102
|
133 typedef typename Visitor::result_type result_type;
|
Chris@102
|
134
|
Chris@102
|
135 template <class Tuple, std::size_t... I>
|
Chris@102
|
136 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) do_call(Tuple t, index_sequence<I...>) const {
|
Chris@102
|
137 return visitor_(std::get<I>(t)...);
|
Chris@102
|
138 }
|
Chris@102
|
139
|
Chris@102
|
140 template <typename Value>
|
Chris@102
|
141 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) operator()(Value& value) const
|
Chris@102
|
142 {
|
Chris@102
|
143 return do_call(
|
Chris@102
|
144 std::tuple_cat(values_, std::tuple<Value&>(value)),
|
Chris@102
|
145 make_index_sequence<sizeof...(Values) + 1>()
|
Chris@102
|
146 );
|
Chris@102
|
147 }
|
Chris@102
|
148 };
|
Chris@102
|
149
|
Chris@102
|
150 }} // namespace detail::variant
|
Chris@102
|
151
|
Chris@102
|
152 template <class Visitor, class T1, class T2, class T3, class... TN>
|
Chris@102
|
153 inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
|
Chris@102
|
154 apply_visitor(const Visitor& visitor, T1& v1, T2& v2, T3& v3, TN&... vn)
|
Chris@102
|
155 {
|
Chris@102
|
156 return ::boost::apply_visitor(
|
Chris@102
|
157 ::boost::detail::variant::make_one_by_one_visitor_and_value_referer(
|
Chris@102
|
158 visitor,
|
Chris@102
|
159 ::boost::detail::variant::forward_as_tuple_simple(v2, v3, vn...),
|
Chris@102
|
160 std::tuple<>()
|
Chris@102
|
161 ),
|
Chris@102
|
162 v1
|
Chris@102
|
163 );
|
Chris@102
|
164 }
|
Chris@102
|
165
|
Chris@102
|
166 template <class Visitor, class T1, class T2, class T3, class... TN>
|
Chris@102
|
167 inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
|
Chris@102
|
168 apply_visitor(Visitor& visitor, T1& v1, T2& v2, T3& v3, TN&... vn)
|
Chris@102
|
169 {
|
Chris@102
|
170 return ::boost::apply_visitor(
|
Chris@102
|
171 ::boost::detail::variant::make_one_by_one_visitor_and_value_referer(
|
Chris@102
|
172 visitor,
|
Chris@102
|
173 ::boost::detail::variant::forward_as_tuple_simple(v2, v3, vn...),
|
Chris@102
|
174 std::tuple<>()
|
Chris@102
|
175 ),
|
Chris@102
|
176 v1
|
Chris@102
|
177 );
|
Chris@102
|
178 }
|
Chris@102
|
179
|
Chris@102
|
180 } // namespace boost
|
Chris@102
|
181
|
Chris@102
|
182 #endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
|
Chris@102
|
183
|