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 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 #include <boost/detail/workaround.hpp>
18 #include <boost/variant/detail/generic_result_type.hpp>
19 
20 #include <boost/variant/detail/apply_visitor_unary.hpp>
21 
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>
26 #endif
27 
28 
29 #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
30 #   include <boost/variant/detail/has_result_type.hpp>
31 #endif
32 
33 namespace boost {
34 
35 //////////////////////////////////////////////////////////////////////////
36 // function template apply_visitor(visitor, visitable1, visitable2)
37 //
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).
41 //
42 
43 namespace detail { namespace variant {
44 
45 template <typename Visitor, typename Value1>
46 class apply_visitor_binary_invoke
47 {
48 public: // visitor typedefs
49 
50     typedef typename Visitor::result_type
51         result_type;
52 
53 private: // representation
54 
55     Visitor& visitor_;
56     Value1& value1_;
57 
58 public: // structors
59 
apply_visitor_binary_invoke(Visitor & visitor,Value1 & value1)60     apply_visitor_binary_invoke(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
61         : visitor_(visitor)
62         , value1_(value1)
63     {
64     }
65 
66 public: // visitor interfaces
67 
68     template <typename Value2>
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)69         BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
70     operator()(Value2& value2)
71     {
72         return visitor_(value1_, value2);
73     }
74 
75 private:
76     apply_visitor_binary_invoke& operator=(const apply_visitor_binary_invoke&);
77 };
78 
79 template <typename Visitor, typename Visitable2>
80 class apply_visitor_binary_unwrap
81 {
82 public: // visitor typedefs
83 
84     typedef typename Visitor::result_type
85         result_type;
86 
87 private: // representation
88 
89     Visitor& visitor_;
90     Visitable2& visitable2_;
91 
92 public: // structors
93 
apply_visitor_binary_unwrap(Visitor & visitor,Visitable2 & visitable2)94     apply_visitor_binary_unwrap(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
95         : visitor_(visitor)
96         , visitable2_(visitable2)
97     {
98     }
99 
100 public: // visitor interfaces
101 
102     template <typename Value1>
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)103         BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
104     operator()(Value1& value1)
105     {
106         apply_visitor_binary_invoke<
107               Visitor
108             , Value1
109             > invoker(visitor_, value1);
110 
111         return boost::apply_visitor(invoker, visitable2_);
112     }
113 
114 private:
115     apply_visitor_binary_unwrap& operator=(const apply_visitor_binary_unwrap&);
116 
117 };
118 
119 }} // namespace detail::variant
120 
121 //
122 // nonconst-visitor version:
123 //
124 
125 #if !BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302))
126 
127 #   define BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(V) \
128     BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename V::result_type) \
129     /**/
130 
131 #else // EDG-based compilers
132 
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) \
137         >::type \
138     /**/
139 
140 #endif // EDG-based compilers workaround
141 
142 template <typename Visitor, typename Visitable1, typename Visitable2>
143 inline
144     BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(Visitor)
apply_visitor(Visitor & visitor,Visitable1 & visitable1,Visitable2 & visitable2)145 apply_visitor(
146       Visitor& visitor
147     , Visitable1& visitable1, Visitable2& visitable2
148     )
149 {
150     ::boost::detail::variant::apply_visitor_binary_unwrap<
151           Visitor, Visitable2
152         > unwrapper(visitor, visitable2);
153 
154     return boost::apply_visitor(unwrapper, visitable1);
155 }
156 
157 #undef BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE
158 
159 //
160 // const-visitor version:
161 //
162 
163 template <typename Visitor, typename Visitable1, typename Visitable2>
164 inline
165     BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
166           typename Visitor::result_type
167         )
apply_visitor(const Visitor & visitor,Visitable1 & visitable1,Visitable2 & visitable2)168 apply_visitor(
169       const Visitor& visitor
170     , Visitable1& visitable1, Visitable2& visitable2
171     )
172 {
173     ::boost::detail::variant::apply_visitor_binary_unwrap<
174           const Visitor, Visitable2
175         > unwrapper(visitor, visitable2);
176 
177     return boost::apply_visitor(unwrapper, visitable1);
178 }
179 
180 
181 #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
182 
183 //////////////////////////////////////////////////////////////////////////
184 // function template apply_visitor(visitor, visitable1, visitable2)
185 //
186 // C++14 part.
187 //
188 
189 namespace detail { namespace variant {
190 
191 template <typename Visitor, typename Value1>
192 class apply_visitor_binary_invoke_cpp14
193 {
194     Visitor& visitor_;
195     Value1& value1_;
196 
197 public: // structors
198 
apply_visitor_binary_invoke_cpp14(Visitor & visitor,Value1 & value1)199     apply_visitor_binary_invoke_cpp14(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
200         : visitor_(visitor)
201         , value1_(value1)
202     {
203     }
204 
205 public: // visitor interfaces
206 
207     template <typename Value2>
operator ()(Value2 & value2)208     decltype(auto) operator()(Value2& value2)
209     {
210         return visitor_(value1_, value2);
211     }
212 
213 private:
214     apply_visitor_binary_invoke_cpp14& operator=(const apply_visitor_binary_invoke_cpp14&);
215 };
216 
217 template <typename Visitor, typename Visitable2>
218 class apply_visitor_binary_unwrap_cpp14
219 {
220     Visitor& visitor_;
221     Visitable2& visitable2_;
222 
223 public: // structors
224 
apply_visitor_binary_unwrap_cpp14(Visitor & visitor,Visitable2 & visitable2)225     apply_visitor_binary_unwrap_cpp14(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
226         : visitor_(visitor)
227         , visitable2_(visitable2)
228     {
229     }
230 
231 public: // visitor interfaces
232 
233     template <typename Value1>
operator ()(Value1 & value1)234     decltype(auto) operator()(Value1& value1)
235     {
236         apply_visitor_binary_invoke_cpp14<
237               Visitor
238             , Value1
239             > invoker(visitor_, value1);
240 
241         return boost::apply_visitor(invoker, visitable2_);
242     }
243 
244 private:
245     apply_visitor_binary_unwrap_cpp14& operator=(const apply_visitor_binary_unwrap_cpp14&);
246 };
247 
248 }} // namespace detail::variant
249 
250 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>>::type * =0)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>
254     >::type* = 0)
255 {
256     ::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
257           Visitor, Visitable2
258         > unwrapper(visitor, visitable2);
259 
260     return boost::apply_visitor(unwrapper, visitable1);
261 }
262 
263 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>>::type * =0)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>
267     >::type* = 0)
268 {
269     ::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
270           const Visitor, Visitable2
271         > unwrapper(visitor, visitable2);
272 
273     return boost::apply_visitor(unwrapper, visitable1);
274 }
275 
276 #endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
277 
278 } // namespace boost
279 
280 #endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP
281