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-2023 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
31namespace 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
41namespace detail { namespace variant {
42
43template <typename Visitor, typename Value1, bool MoveSemantics>
44class apply_visitor_binary_invoke
45{
46public: // visitor typedefs
47
48 typedef typename Visitor::result_type
49 result_type;
50
51private: // representation
52
53 Visitor& visitor_;
54 Value1& value1_;
55
56public: // structors
57
58 apply_visitor_binary_invoke(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
59 : visitor_(visitor)
60 , value1_(value1)
61 {
62 }
63
64public: // 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
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
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
93private:
94 apply_visitor_binary_invoke& operator=(const apply_visitor_binary_invoke&);
95};
96
97template <typename Visitor, typename Visitable2, bool MoveSemantics>
98class apply_visitor_binary_unwrap
99{
100public: // visitor typedefs
101
102 typedef typename Visitor::result_type
103 result_type;
104
105private: // representation
106
107 Visitor& visitor_;
108 Visitable2& visitable2_;
109
110public: // structors
111
112 apply_visitor_binary_unwrap(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
113 : visitor_(visitor)
114 , visitable2_(visitable2)
115 {
116 }
117
118public: // 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
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
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
165private:
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
178template <typename Visitor, typename Visitable1, typename Visitable2>
179inline typename Visitor::result_type
180apply_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
191template <typename Visitor, typename Visitable1, typename Visitable2>
192inline typename Visitor::result_type
193apply_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
210template <typename Visitor, typename Visitable1, typename Visitable2>
211inline typename Visitor::result_type
212apply_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
223template <typename Visitor, typename Visitable1, typename Visitable2>
224inline typename Visitor::result_type
225apply_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
245namespace detail { namespace variant {
246
247template <typename Visitor, typename Value1, bool MoveSemantics>
248class apply_visitor_binary_invoke_cpp14
249{
250 Visitor& visitor_;
251 Value1& value1_;
252
253public: // structors
254
255 apply_visitor_binary_invoke_cpp14(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
256 : visitor_(visitor)
257 , value1_(value1)
258 {
259 }
260
261public: // visitor interfaces
262
263 template <typename Value2>
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>
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
275private:
276 apply_visitor_binary_invoke_cpp14& operator=(const apply_visitor_binary_invoke_cpp14&);
277};
278
279template <typename Visitor, typename Visitable2, bool MoveSemantics>
280class apply_visitor_binary_unwrap_cpp14
281{
282 Visitor& visitor_;
283 Visitable2& visitable2_;
284
285public: // structors
286
287 apply_visitor_binary_unwrap_cpp14(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
288 : visitor_(visitor)
289 , visitable2_(visitable2)
290 {
291 }
292
293public: // visitor interfaces
294
295 template <typename Value1>
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>
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
319private:
320 apply_visitor_binary_unwrap_cpp14& operator=(const apply_visitor_binary_unwrap_cpp14&);
321};
322
323}} // namespace detail::variant
324
325template <typename Visitor, typename Visitable1, typename Visitable2>
326inline 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
339template <typename Visitor, typename Visitable1, typename Visitable2>
340inline 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