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 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 #if BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302))
23 #include <boost/utility/enable_if.hpp>
24 #include <boost/mpl/not.hpp>
25 #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>
35 //////////////////////////////////////////////////////////////////////////
36 // function template apply_visitor(visitor, visitable1, visitable2)
38 // Visits visitable1 and visitable2 such that their values (which we
39 // shall call x and y, respectively) are used as arguments in the
40 // expression visitor(x, y).
43 namespace detail { namespace variant {
45 template <typename Visitor, typename Value1>
46 class apply_visitor_binary_invoke
48 public: // visitor typedefs
50 typedef typename Visitor::result_type
53 private: // representation
60 apply_visitor_binary_invoke(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
66 public: // visitor interfaces
68 template <typename Value2>
69 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
70 operator()(Value2& value2)
72 return visitor_(value1_, value2);
76 apply_visitor_binary_invoke& operator=(const apply_visitor_binary_invoke&);
79 template <typename Visitor, typename Visitable2>
80 class apply_visitor_binary_unwrap
82 public: // visitor typedefs
84 typedef typename Visitor::result_type
87 private: // representation
90 Visitable2& visitable2_;
94 apply_visitor_binary_unwrap(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
96 , visitable2_(visitable2)
100 public: // visitor interfaces
102 template <typename Value1>
103 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
104 operator()(Value1& value1)
106 apply_visitor_binary_invoke<
109 > invoker(visitor_, value1);
111 return boost::apply_visitor(invoker, visitable2_);
115 apply_visitor_binary_unwrap& operator=(const apply_visitor_binary_unwrap&);
119 }} // namespace detail::variant
122 // nonconst-visitor version:
125 #if !BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302))
127 # define BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(V) \
128 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename V::result_type) \
131 #else // EDG-based compilers
133 # define BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(V) \
134 typename enable_if< \
135 mpl::not_< is_const< V > > \
136 , BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename V::result_type) \
140 #endif // EDG-based compilers workaround
142 template <typename Visitor, typename Visitable1, typename Visitable2>
144 BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(Visitor)
147 , Visitable1& visitable1, Visitable2& visitable2
150 ::boost::detail::variant::apply_visitor_binary_unwrap<
152 > unwrapper(visitor, visitable2);
154 return boost::apply_visitor(unwrapper, visitable1);
157 #undef BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE
160 // const-visitor version:
163 template <typename Visitor, typename Visitable1, typename Visitable2>
165 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
166 typename Visitor::result_type
169 const Visitor& visitor
170 , Visitable1& visitable1, Visitable2& visitable2
173 ::boost::detail::variant::apply_visitor_binary_unwrap<
174 const Visitor, Visitable2
175 > unwrapper(visitor, visitable2);
177 return boost::apply_visitor(unwrapper, visitable1);
181 #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
183 //////////////////////////////////////////////////////////////////////////
184 // function template apply_visitor(visitor, visitable1, visitable2)
189 namespace detail { namespace variant {
191 template <typename Visitor, typename Value1>
192 class apply_visitor_binary_invoke_cpp14
199 apply_visitor_binary_invoke_cpp14(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
205 public: // visitor interfaces
207 template <typename Value2>
208 decltype(auto) operator()(Value2& value2)
210 return visitor_(value1_, value2);
214 apply_visitor_binary_invoke_cpp14& operator=(const apply_visitor_binary_invoke_cpp14&);
217 template <typename Visitor, typename Visitable2>
218 class apply_visitor_binary_unwrap_cpp14
221 Visitable2& visitable2_;
225 apply_visitor_binary_unwrap_cpp14(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
227 , visitable2_(visitable2)
231 public: // visitor interfaces
233 template <typename Value1>
234 decltype(auto) operator()(Value1& value1)
236 apply_visitor_binary_invoke_cpp14<
239 > invoker(visitor_, value1);
241 return boost::apply_visitor(invoker, visitable2_);
245 apply_visitor_binary_unwrap_cpp14& operator=(const apply_visitor_binary_unwrap_cpp14&);
248 }} // namespace detail::variant
250 template <typename Visitor, typename Visitable1, typename Visitable2>
251 inline decltype(auto) apply_visitor(Visitor& visitor, Visitable1& visitable1, Visitable2& visitable2,
252 typename boost::disable_if<
253 boost::detail::variant::has_result_type<Visitor>
256 ::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
258 > unwrapper(visitor, visitable2);
260 return boost::apply_visitor(unwrapper, visitable1);
263 template <typename Visitor, typename Visitable1, typename Visitable2>
264 inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable1& visitable1, Visitable2& visitable2,
265 typename boost::disable_if<
266 boost::detail::variant::has_result_type<Visitor>
269 ::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
270 const Visitor, Visitable2
271 > unwrapper(visitor, visitable2);
273 return boost::apply_visitor(unwrapper, visitable1);
276 #endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
280 #endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP