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