1 //-----------------------------------------------------------------------------
2 // boost variant/detail/apply_visitor_binary.hpp header file
3 // See http://www.boost.org for updates, documentation, and revision history.
4 //-----------------------------------------------------------------------------
5 //
6 // Copyright (c) 2002-2003 Eric Friedman
7 // Copyright (c) 2014-2020 Antony Polukhin
8 //
9 // Distributed under the Boost Software License, Version 1.0. (See
10 // accompanying file LICENSE_1_0.txt or copy at
11 // http://www.boost.org/LICENSE_1_0.txt)
12
13 #ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP
14 #define BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP
15
16 #include <boost/config.hpp>
17
18 #include <boost/variant/detail/apply_visitor_unary.hpp>
19
20 #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
21 # include <boost/variant/detail/has_result_type.hpp>
22 #endif
23
24 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
25 # include <boost/core/enable_if.hpp>
26 # include <boost/type_traits/is_lvalue_reference.hpp>
27 # include <boost/type_traits/is_same.hpp>
28 # include <boost/move/utility_core.hpp> // for boost::move, boost::forward
29 #endif
30
31 namespace boost {
32
33 //////////////////////////////////////////////////////////////////////////
34 // function template apply_visitor(visitor, visitable1, visitable2)
35 //
36 // Visits visitable1 and visitable2 such that their values (which we
37 // shall call x and y, respectively) are used as arguments in the
38 // expression visitor(x, y).
39 //
40
41 namespace detail { namespace variant {
42
43 template <typename Visitor, typename Value1, bool MoveSemantics>
44 class apply_visitor_binary_invoke
45 {
46 public: // visitor typedefs
47
48 typedef typename Visitor::result_type
49 result_type;
50
51 private: // representation
52
53 Visitor& visitor_;
54 Value1& value1_;
55
56 public: // structors
57
apply_visitor_binary_invoke(Visitor & visitor,Value1 & value1)58 apply_visitor_binary_invoke(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
59 : visitor_(visitor)
60 , value1_(value1)
61 {
62 }
63
64 public: // visitor interfaces
65
66 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
67
68 template <typename Value2>
69 typename enable_if_c<MoveSemantics && is_same<Value2, Value2>::value, result_type>::type
operator ()(Value2 && value2)70 operator()(Value2&& value2)
71 {
72 return visitor_(::boost::move(value1_), ::boost::forward<Value2>(value2));
73 }
74
75 template <typename Value2>
76 typename disable_if_c<MoveSemantics && is_same<Value2, Value2>::value, result_type>::type
operator ()(Value2 && value2)77 operator()(Value2&& value2)
78 {
79 return visitor_(value1_, ::boost::forward<Value2>(value2));
80 }
81
82 #else
83
84 template <typename Value2>
85 result_type
86 operator()(Value2& value2)
87 {
88 return visitor_(value1_, value2);
89 }
90
91 #endif
92
93 private:
94 apply_visitor_binary_invoke& operator=(const apply_visitor_binary_invoke&);
95 };
96
97 template <typename Visitor, typename Visitable2, bool MoveSemantics>
98 class apply_visitor_binary_unwrap
99 {
100 public: // visitor typedefs
101
102 typedef typename Visitor::result_type
103 result_type;
104
105 private: // representation
106
107 Visitor& visitor_;
108 Visitable2& visitable2_;
109
110 public: // structors
111
apply_visitor_binary_unwrap(Visitor & visitor,Visitable2 & visitable2)112 apply_visitor_binary_unwrap(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
113 : visitor_(visitor)
114 , visitable2_(visitable2)
115 {
116 }
117
118 public: // visitor interfaces
119
120 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
121
122 template <typename Value1>
123 typename enable_if_c<MoveSemantics && is_same<Value1, Value1>::value, result_type>::type
operator ()(Value1 && value1)124 operator()(Value1&& value1)
125 {
126 apply_visitor_binary_invoke<
127 Visitor
128 , Value1
129 , ! ::boost::is_lvalue_reference<Value1>::value
130 > invoker(visitor_, value1);
131
132 return boost::apply_visitor(invoker, ::boost::move(visitable2_));
133 }
134
135 template <typename Value1>
136 typename disable_if_c<MoveSemantics && is_same<Value1, Value1>::value, result_type>::type
operator ()(Value1 && value1)137 operator()(Value1&& value1)
138 {
139 apply_visitor_binary_invoke<
140 Visitor
141 , Value1
142 , ! ::boost::is_lvalue_reference<Value1>::value
143 > invoker(visitor_, value1);
144
145 return boost::apply_visitor(invoker, visitable2_);
146 }
147
148 #else
149
150 template <typename Value1>
151 result_type
152 operator()(Value1& value1)
153 {
154 apply_visitor_binary_invoke<
155 Visitor
156 , Value1
157 , false
158 > invoker(visitor_, value1);
159
160 return boost::apply_visitor(invoker, visitable2_);
161 }
162
163 #endif
164
165 private:
166 apply_visitor_binary_unwrap& operator=(const apply_visitor_binary_unwrap&);
167
168 };
169
170 }} // namespace detail::variant
171
172 //
173 // nonconst-visitor version:
174 //
175
176 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
177
178 template <typename Visitor, typename Visitable1, typename Visitable2>
179 inline typename Visitor::result_type
apply_visitor(Visitor & visitor,Visitable1 && visitable1,Visitable2 && visitable2)180 apply_visitor( Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2)
181 {
182 ::boost::detail::variant::apply_visitor_binary_unwrap<
183 Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
184 > unwrapper(visitor, visitable2);
185
186 return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
187 }
188
189 #else
190
191 template <typename Visitor, typename Visitable1, typename Visitable2>
192 inline typename Visitor::result_type
apply_visitor(Visitor & visitor,Visitable1 & visitable1,Visitable2 & visitable2)193 apply_visitor( Visitor& visitor, Visitable1& visitable1, Visitable2& visitable2)
194 {
195 ::boost::detail::variant::apply_visitor_binary_unwrap<
196 Visitor, Visitable2, false
197 > unwrapper(visitor, visitable2);
198
199 return boost::apply_visitor(unwrapper, visitable1);
200 }
201
202 #endif
203
204 //
205 // const-visitor version:
206 //
207
208 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
209
210 template <typename Visitor, typename Visitable1, typename Visitable2>
211 inline typename Visitor::result_type
apply_visitor(const Visitor & visitor,Visitable1 && visitable1,Visitable2 && visitable2)212 apply_visitor( const Visitor& visitor , Visitable1&& visitable1 , Visitable2&& visitable2)
213 {
214 ::boost::detail::variant::apply_visitor_binary_unwrap<
215 const Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
216 > unwrapper(visitor, visitable2);
217
218 return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
219 }
220
221 #else
222
223 template <typename Visitor, typename Visitable1, typename Visitable2>
224 inline typename Visitor::result_type
apply_visitor(const Visitor & visitor,Visitable1 & visitable1,Visitable2 & visitable2)225 apply_visitor( const Visitor& visitor , Visitable1& visitable1 , Visitable2& visitable2)
226 {
227 ::boost::detail::variant::apply_visitor_binary_unwrap<
228 const Visitor, Visitable2, false
229 > unwrapper(visitor, visitable2);
230
231 return boost::apply_visitor(unwrapper, visitable1);
232 }
233
234 #endif
235
236
237 #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
238
239 //////////////////////////////////////////////////////////////////////////
240 // function template apply_visitor(visitor, visitable1, visitable2)
241 //
242 // C++14 part.
243 //
244
245 namespace detail { namespace variant {
246
247 template <typename Visitor, typename Value1, bool MoveSemantics>
248 class apply_visitor_binary_invoke_cpp14
249 {
250 Visitor& visitor_;
251 Value1& value1_;
252
253 public: // structors
254
apply_visitor_binary_invoke_cpp14(Visitor & visitor,Value1 & value1)255 apply_visitor_binary_invoke_cpp14(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
256 : visitor_(visitor)
257 , value1_(value1)
258 {
259 }
260
261 public: // visitor interfaces
262
263 template <typename Value2>
operator ()(Value2 && value2,typename enable_if_c<MoveSemantics && is_same<Value2,Value2>::value,bool>::type=true)264 decltype(auto) operator()(Value2&& value2, typename enable_if_c<MoveSemantics && is_same<Value2, Value2>::value, bool>::type = true)
265 {
266 return visitor_(::boost::move(value1_), ::boost::forward<Value2>(value2));
267 }
268
269 template <typename Value2>
operator ()(Value2 && value2,typename disable_if_c<MoveSemantics && is_same<Value2,Value2>::value,bool>::type=true)270 decltype(auto) operator()(Value2&& value2, typename disable_if_c<MoveSemantics && is_same<Value2, Value2>::value, bool>::type = true)
271 {
272 return visitor_(value1_, ::boost::forward<Value2>(value2));
273 }
274
275 private:
276 apply_visitor_binary_invoke_cpp14& operator=(const apply_visitor_binary_invoke_cpp14&);
277 };
278
279 template <typename Visitor, typename Visitable2, bool MoveSemantics>
280 class apply_visitor_binary_unwrap_cpp14
281 {
282 Visitor& visitor_;
283 Visitable2& visitable2_;
284
285 public: // structors
286
apply_visitor_binary_unwrap_cpp14(Visitor & visitor,Visitable2 & visitable2)287 apply_visitor_binary_unwrap_cpp14(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
288 : visitor_(visitor)
289 , visitable2_(visitable2)
290 {
291 }
292
293 public: // visitor interfaces
294
295 template <typename Value1>
operator ()(Value1 && value1,typename enable_if_c<MoveSemantics && is_same<Value1,Value1>::value,bool>::type=true)296 decltype(auto) operator()(Value1&& value1, typename enable_if_c<MoveSemantics && is_same<Value1, Value1>::value, bool>::type = true)
297 {
298 apply_visitor_binary_invoke_cpp14<
299 Visitor
300 , Value1
301 , ! ::boost::is_lvalue_reference<Value1>::value
302 > invoker(visitor_, value1);
303
304 return boost::apply_visitor(invoker, ::boost::move(visitable2_));
305 }
306
307 template <typename Value1>
operator ()(Value1 && value1,typename disable_if_c<MoveSemantics && is_same<Value1,Value1>::value,bool>::type=true)308 decltype(auto) operator()(Value1&& value1, typename disable_if_c<MoveSemantics && is_same<Value1, Value1>::value, bool>::type = true)
309 {
310 apply_visitor_binary_invoke_cpp14<
311 Visitor
312 , Value1
313 , ! ::boost::is_lvalue_reference<Value1>::value
314 > invoker(visitor_, value1);
315
316 return boost::apply_visitor(invoker, visitable2_);
317 }
318
319 private:
320 apply_visitor_binary_unwrap_cpp14& operator=(const apply_visitor_binary_unwrap_cpp14&);
321 };
322
323 }} // namespace detail::variant
324
325 template <typename Visitor, typename Visitable1, typename Visitable2>
apply_visitor(Visitor & visitor,Visitable1 && visitable1,Visitable2 && visitable2,typename boost::disable_if<boost::detail::variant::has_result_type<Visitor>,bool>::type=true)326 inline decltype(auto) apply_visitor(Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2,
327 typename boost::disable_if<
328 boost::detail::variant::has_result_type<Visitor>,
329 bool
330 >::type = true)
331 {
332 ::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
333 Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
334 > unwrapper(visitor, visitable2);
335
336 return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
337 }
338
339 template <typename Visitor, typename Visitable1, typename Visitable2>
apply_visitor(const Visitor & visitor,Visitable1 && visitable1,Visitable2 && visitable2,typename boost::disable_if<boost::detail::variant::has_result_type<Visitor>,bool>::type=true)340 inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2,
341 typename boost::disable_if<
342 boost::detail::variant::has_result_type<Visitor>,
343 bool
344 >::type = true)
345 {
346 ::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
347 const Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
348 > unwrapper(visitor, visitable2);
349
350 return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
351 }
352
353
354 #endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
355
356 } // namespace boost
357
358 #endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP
359