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-2017 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>
17 #include <boost/detail/workaround.hpp>
18 #include <boost/variant/detail/generic_result_type.hpp>
20 #include <boost/variant/detail/apply_visitor_unary.hpp>
22 #include <boost/utility/enable_if.hpp>
24 #if BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302))
25 #include <boost/mpl/not.hpp>
26 #include <boost/type_traits/is_const.hpp>
29 #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
30 # include <boost/variant/detail/has_result_type.hpp>
33 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
34 # include <boost/type_traits/is_lvalue_reference.hpp>
35 # include <boost/type_traits/is_same.hpp>
36 # include <boost/move/move.hpp>
37 # include <boost/move/utility.hpp>
42 //////////////////////////////////////////////////////////////////////////
43 // function template apply_visitor(visitor, visitable1, visitable2)
45 // Visits visitable1 and visitable2 such that their values (which we
46 // shall call x and y, respectively) are used as arguments in the
47 // expression visitor(x, y).
50 namespace detail { namespace variant {
52 template <typename Visitor, typename Value1, bool MoveSemantics>
53 class apply_visitor_binary_invoke
55 public: // visitor typedefs
57 typedef typename Visitor::result_type
60 private: // representation
67 apply_visitor_binary_invoke(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
73 public: // visitor interfaces
75 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
77 template <typename Value2>
78 typename enable_if_c<MoveSemantics && is_same<Value2, Value2>::value, BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)>::type
79 operator()(Value2&& value2)
81 return visitor_(::boost::move(value1_), ::boost::forward<Value2>(value2));
84 template <typename Value2>
85 typename disable_if_c<MoveSemantics && is_same<Value2, Value2>::value, BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)>::type
86 operator()(Value2&& value2)
88 return visitor_(value1_, ::boost::forward<Value2>(value2));
93 template <typename Value2>
94 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
95 operator()(Value2& value2)
97 return visitor_(value1_, value2);
103 apply_visitor_binary_invoke& operator=(const apply_visitor_binary_invoke&);
106 template <typename Visitor, typename Visitable2, bool MoveSemantics>
107 class apply_visitor_binary_unwrap
109 public: // visitor typedefs
111 typedef typename Visitor::result_type
114 private: // representation
117 Visitable2& visitable2_;
121 apply_visitor_binary_unwrap(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
123 , visitable2_(visitable2)
127 public: // visitor interfaces
129 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
131 template <typename Value1>
132 typename enable_if_c<MoveSemantics && is_same<Value1, Value1>::value, BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)>::type
133 operator()(Value1&& value1)
135 apply_visitor_binary_invoke<
138 , ! ::boost::is_lvalue_reference<Value1>::value
139 > invoker(visitor_, value1);
141 return boost::apply_visitor(invoker, ::boost::move(visitable2_));
144 template <typename Value1>
145 typename disable_if_c<MoveSemantics && is_same<Value1, Value1>::value, BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)>::type
146 operator()(Value1&& value1)
148 apply_visitor_binary_invoke<
151 , ! ::boost::is_lvalue_reference<Value1>::value
152 > invoker(visitor_, value1);
154 return boost::apply_visitor(invoker, visitable2_);
159 template <typename Value1>
160 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
161 operator()(Value1& value1)
163 apply_visitor_binary_invoke<
167 > invoker(visitor_, value1);
169 return boost::apply_visitor(invoker, visitable2_);
175 apply_visitor_binary_unwrap& operator=(const apply_visitor_binary_unwrap&);
179 }} // namespace detail::variant
182 // nonconst-visitor version:
185 #if !BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302))
187 # define BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(V) \
188 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename V::result_type) \
191 #else // EDG-based compilers
193 # define BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(V) \
194 typename enable_if< \
195 mpl::not_< is_const< V > > \
196 , BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename V::result_type) \
200 #endif // EDG-based compilers workaround
202 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
204 template <typename Visitor, typename Visitable1, typename Visitable2>
206 BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(Visitor)
207 apply_visitor( Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2)
209 ::boost::detail::variant::apply_visitor_binary_unwrap<
210 Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
211 > unwrapper(visitor, visitable2);
213 return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
218 template <typename Visitor, typename Visitable1, typename Visitable2>
220 BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(Visitor)
221 apply_visitor( Visitor& visitor, Visitable1& visitable1, Visitable2& visitable2)
223 ::boost::detail::variant::apply_visitor_binary_unwrap<
224 Visitor, Visitable2, false
225 > unwrapper(visitor, visitable2);
227 return boost::apply_visitor(unwrapper, visitable1);
232 #undef BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE
235 // const-visitor version:
238 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
240 template <typename Visitor, typename Visitable1, typename Visitable2>
242 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
243 typename Visitor::result_type
245 apply_visitor( const Visitor& visitor , Visitable1&& visitable1 , Visitable2&& visitable2)
247 ::boost::detail::variant::apply_visitor_binary_unwrap<
248 const Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
249 > unwrapper(visitor, visitable2);
251 return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
256 template <typename Visitor, typename Visitable1, typename Visitable2>
258 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
259 typename Visitor::result_type
261 apply_visitor( const Visitor& visitor , Visitable1& visitable1 , Visitable2& visitable2)
263 ::boost::detail::variant::apply_visitor_binary_unwrap<
264 const Visitor, Visitable2, false
265 > unwrapper(visitor, visitable2);
267 return boost::apply_visitor(unwrapper, visitable1);
273 #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
275 //////////////////////////////////////////////////////////////////////////
276 // function template apply_visitor(visitor, visitable1, visitable2)
281 namespace detail { namespace variant {
283 template <typename Visitor, typename Value1, bool MoveSemantics>
284 class apply_visitor_binary_invoke_cpp14
291 apply_visitor_binary_invoke_cpp14(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
297 public: // visitor interfaces
299 template <typename Value2>
300 decltype(auto) operator()(Value2&& value2, typename enable_if_c<MoveSemantics && is_same<Value2, Value2>::value>::type* = 0)
302 return visitor_(::boost::move(value1_), ::boost::forward<Value2>(value2));
305 template <typename Value2>
306 decltype(auto) operator()(Value2&& value2, typename disable_if_c<MoveSemantics && is_same<Value2, Value2>::value>::type* = 0)
308 return visitor_(value1_, ::boost::forward<Value2>(value2));
312 apply_visitor_binary_invoke_cpp14& operator=(const apply_visitor_binary_invoke_cpp14&);
315 template <typename Visitor, typename Visitable2, bool MoveSemantics>
316 class apply_visitor_binary_unwrap_cpp14
319 Visitable2& visitable2_;
323 apply_visitor_binary_unwrap_cpp14(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
325 , visitable2_(visitable2)
329 public: // visitor interfaces
331 template <typename Value1>
332 decltype(auto) operator()(Value1&& value1, typename enable_if_c<MoveSemantics && is_same<Value1, Value1>::value>::type* = 0)
334 apply_visitor_binary_invoke_cpp14<
337 , ! ::boost::is_lvalue_reference<Value1>::value
338 > invoker(visitor_, value1);
340 return boost::apply_visitor(invoker, ::boost::move(visitable2_));
343 template <typename Value1>
344 decltype(auto) operator()(Value1&& value1, typename disable_if_c<MoveSemantics && is_same<Value1, Value1>::value>::type* = 0)
346 apply_visitor_binary_invoke_cpp14<
349 , ! ::boost::is_lvalue_reference<Value1>::value
350 > invoker(visitor_, value1);
352 return boost::apply_visitor(invoker, visitable2_);
356 apply_visitor_binary_unwrap_cpp14& operator=(const apply_visitor_binary_unwrap_cpp14&);
359 }} // namespace detail::variant
361 template <typename Visitor, typename Visitable1, typename Visitable2>
362 inline decltype(auto) apply_visitor(Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2,
363 typename boost::disable_if<
364 boost::detail::variant::has_result_type<Visitor>
367 ::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
368 Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
369 > unwrapper(visitor, visitable2);
371 return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
374 template <typename Visitor, typename Visitable1, typename Visitable2>
375 inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2,
376 typename boost::disable_if<
377 boost::detail::variant::has_result_type<Visitor>
380 ::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
381 const Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
382 > unwrapper(visitor, visitable2);
384 return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
388 #endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
392 #endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP