1 //-----------------------------------------------------------------------------
2 // boost variant/detail/apply_visitor_binary.hpp header file
3 // See http://www.boost.org for updates, documentation, and revision history.
4 //-----------------------------------------------------------------------------
6 // Copyright (c) 2002-2003 Eric Friedman
7 // Copyright (c) 2014-2019 Antony Polukhin
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)
13 #ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP
14 #define BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP
16 #include <boost/config.hpp>
18 #include <boost/variant/detail/apply_visitor_unary.hpp>
20 #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
21 # include <boost/variant/detail/has_result_type.hpp>
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/move.hpp>
29 # include <boost/move/utility.hpp>
34 //////////////////////////////////////////////////////////////////////////
35 // function template apply_visitor(visitor, visitable1, visitable2)
37 // Visits visitable1 and visitable2 such that their values (which we
38 // shall call x and y, respectively) are used as arguments in the
39 // expression visitor(x, y).
42 namespace detail { namespace variant {
44 template <typename Visitor, typename Value1, bool MoveSemantics>
45 class apply_visitor_binary_invoke
47 public: // visitor typedefs
49 typedef typename Visitor::result_type
52 private: // representation
59 apply_visitor_binary_invoke(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
65 public: // visitor interfaces
67 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
69 template <typename Value2>
70 typename enable_if_c<MoveSemantics && is_same<Value2, Value2>::value, result_type>::type
71 operator()(Value2&& value2)
73 return visitor_(::boost::move(value1_), ::boost::forward<Value2>(value2));
76 template <typename Value2>
77 typename disable_if_c<MoveSemantics && is_same<Value2, Value2>::value, result_type>::type
78 operator()(Value2&& value2)
80 return visitor_(value1_, ::boost::forward<Value2>(value2));
85 template <typename Value2>
87 operator()(Value2& value2)
89 return visitor_(value1_, value2);
95 apply_visitor_binary_invoke& operator=(const apply_visitor_binary_invoke&);
98 template <typename Visitor, typename Visitable2, bool MoveSemantics>
99 class apply_visitor_binary_unwrap
101 public: // visitor typedefs
103 typedef typename Visitor::result_type
106 private: // representation
109 Visitable2& visitable2_;
113 apply_visitor_binary_unwrap(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
115 , visitable2_(visitable2)
119 public: // visitor interfaces
121 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
123 template <typename Value1>
124 typename enable_if_c<MoveSemantics && is_same<Value1, Value1>::value, result_type>::type
125 operator()(Value1&& value1)
127 apply_visitor_binary_invoke<
130 , ! ::boost::is_lvalue_reference<Value1>::value
131 > invoker(visitor_, value1);
133 return boost::apply_visitor(invoker, ::boost::move(visitable2_));
136 template <typename Value1>
137 typename disable_if_c<MoveSemantics && is_same<Value1, Value1>::value, result_type>::type
138 operator()(Value1&& value1)
140 apply_visitor_binary_invoke<
143 , ! ::boost::is_lvalue_reference<Value1>::value
144 > invoker(visitor_, value1);
146 return boost::apply_visitor(invoker, visitable2_);
151 template <typename Value1>
153 operator()(Value1& value1)
155 apply_visitor_binary_invoke<
159 > invoker(visitor_, value1);
161 return boost::apply_visitor(invoker, visitable2_);
167 apply_visitor_binary_unwrap& operator=(const apply_visitor_binary_unwrap&);
171 }} // namespace detail::variant
174 // nonconst-visitor version:
177 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
179 template <typename Visitor, typename Visitable1, typename Visitable2>
180 inline typename Visitor::result_type
181 apply_visitor( Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2)
183 ::boost::detail::variant::apply_visitor_binary_unwrap<
184 Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
185 > unwrapper(visitor, visitable2);
187 return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
192 template <typename Visitor, typename Visitable1, typename Visitable2>
193 inline typename Visitor::result_type
194 apply_visitor( Visitor& visitor, Visitable1& visitable1, Visitable2& visitable2)
196 ::boost::detail::variant::apply_visitor_binary_unwrap<
197 Visitor, Visitable2, false
198 > unwrapper(visitor, visitable2);
200 return boost::apply_visitor(unwrapper, visitable1);
206 // const-visitor version:
209 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
211 template <typename Visitor, typename Visitable1, typename Visitable2>
212 inline typename Visitor::result_type
213 apply_visitor( const Visitor& visitor , Visitable1&& visitable1 , Visitable2&& visitable2)
215 ::boost::detail::variant::apply_visitor_binary_unwrap<
216 const Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
217 > unwrapper(visitor, visitable2);
219 return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
224 template <typename Visitor, typename Visitable1, typename Visitable2>
225 inline typename Visitor::result_type
226 apply_visitor( const Visitor& visitor , Visitable1& visitable1 , Visitable2& visitable2)
228 ::boost::detail::variant::apply_visitor_binary_unwrap<
229 const Visitor, Visitable2, false
230 > unwrapper(visitor, visitable2);
232 return boost::apply_visitor(unwrapper, visitable1);
238 #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
240 //////////////////////////////////////////////////////////////////////////
241 // function template apply_visitor(visitor, visitable1, visitable2)
246 namespace detail { namespace variant {
248 template <typename Visitor, typename Value1, bool MoveSemantics>
249 class apply_visitor_binary_invoke_cpp14
256 apply_visitor_binary_invoke_cpp14(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
262 public: // visitor interfaces
264 template <typename Value2>
265 decltype(auto) operator()(Value2&& value2, typename enable_if_c<MoveSemantics && is_same<Value2, Value2>::value>::type* = 0)
267 return visitor_(::boost::move(value1_), ::boost::forward<Value2>(value2));
270 template <typename Value2>
271 decltype(auto) operator()(Value2&& value2, typename disable_if_c<MoveSemantics && is_same<Value2, Value2>::value>::type* = 0)
273 return visitor_(value1_, ::boost::forward<Value2>(value2));
277 apply_visitor_binary_invoke_cpp14& operator=(const apply_visitor_binary_invoke_cpp14&);
280 template <typename Visitor, typename Visitable2, bool MoveSemantics>
281 class apply_visitor_binary_unwrap_cpp14
284 Visitable2& visitable2_;
288 apply_visitor_binary_unwrap_cpp14(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
290 , visitable2_(visitable2)
294 public: // visitor interfaces
296 template <typename Value1>
297 decltype(auto) operator()(Value1&& value1, typename enable_if_c<MoveSemantics && is_same<Value1, Value1>::value>::type* = 0)
299 apply_visitor_binary_invoke_cpp14<
302 , ! ::boost::is_lvalue_reference<Value1>::value
303 > invoker(visitor_, value1);
305 return boost::apply_visitor(invoker, ::boost::move(visitable2_));
308 template <typename Value1>
309 decltype(auto) operator()(Value1&& value1, typename disable_if_c<MoveSemantics && is_same<Value1, Value1>::value>::type* = 0)
311 apply_visitor_binary_invoke_cpp14<
314 , ! ::boost::is_lvalue_reference<Value1>::value
315 > invoker(visitor_, value1);
317 return boost::apply_visitor(invoker, visitable2_);
321 apply_visitor_binary_unwrap_cpp14& operator=(const apply_visitor_binary_unwrap_cpp14&);
324 }} // namespace detail::variant
326 template <typename Visitor, typename Visitable1, typename Visitable2>
327 inline decltype(auto) apply_visitor(Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2,
328 typename boost::disable_if<
329 boost::detail::variant::has_result_type<Visitor>
332 ::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
333 Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
334 > unwrapper(visitor, visitable2);
336 return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
339 template <typename Visitor, typename Visitable1, typename Visitable2>
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>
345 ::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
346 const Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
347 > unwrapper(visitor, visitable2);
349 return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
353 #endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
357 #endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP