1 //-----------------------------------------------------------------------------
2 // boost-libs variant/test/auto_visitors.cpp source file
3 // See http://www.boost.org for updates, documentation, and revision history.
4 //-----------------------------------------------------------------------------
6 // Copyright (c) 2014-2019 Antony Polukhin
8 // Distributed under the Boost Software License, Version 1.0. (See
9 // accompanying file LICENSE_1_0.txt or copy at
10 // http://www.boost.org/LICENSE_1_0.txt)
12 #include "boost/config.hpp"
14 #include "boost/core/lightweight_test.hpp"
15 #include "boost/variant.hpp"
16 #include "boost/variant/multivisitors.hpp"
17 #include "boost/lexical_cast.hpp"
19 #include <boost/noncopyable.hpp>
20 #include <boost/core/ignore_unused.hpp>
22 namespace has_result_type_tests
{
25 typedef T result_type
;
28 struct s1
: wrap
<int> {};
29 struct s2
: wrap
<int&> {};
30 struct s3
: wrap
<const int&> {};
32 struct s5
: wrap
<int*> {};
33 struct s6
: wrap
<int**> {};
34 struct s7
: wrap
<const int*> {};
35 struct s8
: wrap
<boost::noncopyable
> {};
36 struct s9
: wrap
<boost::noncopyable
&> {};
37 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
38 struct s10
: wrap
<boost::noncopyable
&&> {};
40 struct s11
: wrap
<const boost::noncopyable
&> {};
41 struct s12
: wrap
<const boost::noncopyable
*> {};
42 struct s13
: wrap
<boost::noncopyable
*> {};
43 struct s14
{ typedef int result_type
; };
44 struct s15
{ typedef int& result_type
; };
45 struct s16
{ typedef const int& result_type
; };
49 void test_has_result_type_triat() {
50 using namespace has_result_type_tests
;
51 using boost::detail::variant::has_result_type
;
53 BOOST_TEST(has_result_type
<s1
>::value
);
54 BOOST_TEST(has_result_type
<s2
>::value
);
55 BOOST_TEST(has_result_type
<s3
>::value
);
56 BOOST_TEST(!has_result_type
<s4
>::value
);
57 BOOST_TEST(has_result_type
<s5
>::value
);
58 BOOST_TEST(has_result_type
<s6
>::value
);
59 BOOST_TEST(has_result_type
<s7
>::value
);
60 BOOST_TEST(has_result_type
<s8
>::value
);
61 BOOST_TEST(has_result_type
<s9
>::value
);
62 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
63 BOOST_TEST(has_result_type
<s10
>::value
);
65 BOOST_TEST(has_result_type
<s11
>::value
);
66 BOOST_TEST(has_result_type
<s12
>::value
);
67 BOOST_TEST(has_result_type
<s13
>::value
);
68 BOOST_TEST(has_result_type
<s14
>::value
);
69 BOOST_TEST(has_result_type
<s15
>::value
);
70 BOOST_TEST(has_result_type
<s16
>::value
);
73 struct lex_streamer_explicit
: boost::static_visitor
<std::string
> {
75 const char* operator()(const T
& ) {
79 template <class T1
, class T2
>
80 const char* operator()(const T1
& , const T2
& ) {
88 typedef boost::variant
<int, std::string
, double> variant_type
;
89 variant_type
v2("10"), v1("100");
91 lex_streamer_explicit visitor_ref
;
93 // Must return instance of std::string
94 BOOST_TEST(boost::apply_visitor(visitor_ref
, v2
).c_str() == std::string("10"));
95 BOOST_TEST(boost::apply_visitor(visitor_ref
, v2
, v1
).c_str() == std::string("100"));
99 // Most part of tests from this file require decltype(auto)
101 #ifdef BOOST_NO_CXX14_DECLTYPE_AUTO
123 struct lex_streamer
{
125 std::string
operator()(const T
& val
) const {
126 return boost::lexical_cast
<std::string
>(val
);
130 struct lex_streamer_void
{
132 void operator()(const T
& val
) const {
133 std::cout
<< val
<< std::endl
;
137 template <class T1
, class T2
>
138 void operator()(const T1
& val
, const T2
& val2
) const {
139 std::cout
<< val
<< '+' << val2
<< std::endl
;
143 template <class T1
, class T2
, class T3
>
144 void operator()(const T1
& val
, const T2
& val2
, const T3
& val3
) const {
145 std::cout
<< val
<< '+' << val2
<< '+' << val3
<< std::endl
;
150 struct lex_streamer2
{
154 const char* operator()(const T
& /*val*/) const {
158 template <class T1
, class T2
>
159 const char* operator()(const T1
& /*v1*/, const T2
& /*v2*/) const {
164 template <class T1
, class T2
, class T3
>
165 const char* operator()(const T1
& /*v1*/, const T2
& /*v2*/, const T3
& /*v3*/) const {
170 std::string
& operator()(const T
& val
) {
171 res
= boost::lexical_cast
<std::string
>(val
);
176 template <class T1
, class T2
>
177 std::string
& operator()(const T1
& v1
, const T2
& v2
) {
178 res
= boost::lexical_cast
<std::string
>(v1
) + "+" + boost::lexical_cast
<std::string
>(v2
);
183 template <class T1
, class T2
, class T3
>
184 std::string
& operator()(const T1
& v1
, const T2
& v2
, const T3
& v3
) {
185 res
= boost::lexical_cast
<std::string
>(v1
) + "+" + boost::lexical_cast
<std::string
>(v2
)
186 + "+" + boost::lexical_cast
<std::string
>(v3
);
191 #ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
192 # define BOOST_TEST_IF_HAS_VARIADIC(x) BOOST_TEST(x)
194 # define BOOST_TEST_IF_HAS_VARIADIC(x) /**/
199 typedef boost::variant
<int, std::string
, double> variant_type
;
200 variant_type
v1(1), v2("10"), v3(100.0);
201 lex_streamer lex_streamer_visitor
;
203 BOOST_TEST(boost::apply_visitor(lex_streamer(), v1
) == "1");
204 BOOST_TEST_IF_HAS_VARIADIC(boost::apply_visitor(lex_streamer_visitor
)(v1
) == "1");
205 BOOST_TEST(boost::apply_visitor(lex_streamer(), v2
) == "10");
206 BOOST_TEST_IF_HAS_VARIADIC(boost::apply_visitor(lex_streamer_visitor
)(v2
) == "10");
208 #ifndef BOOST_NO_CXX14_GENERIC_LAMBDAS
209 BOOST_TEST(boost::apply_visitor([](auto v
) { return boost::lexical_cast
<std::string
>(v
); }, v1
) == "1");
210 BOOST_TEST(boost::apply_visitor([](auto v
) { return boost::lexical_cast
<std::string
>(v
); }, v2
) == "10");
212 // Retun type must be the same in all instances, so this code does not compile
213 //boost::variant<int, short, unsigned> v_diff_types(1);
214 //BOOST_TEST(boost::apply_visitor([](auto v) { return v; }, v_diff_types) == 1);
216 boost::apply_visitor([](auto v
) { std::cout
<< v
<< std::endl
; }, v1
);
217 boost::apply_visitor([](auto v
) { std::cout
<< v
<< std::endl
; }, v2
);
220 lex_streamer2 visitor_ref
;
221 BOOST_TEST(boost::apply_visitor(visitor_ref
, v1
) == "1");
222 BOOST_TEST(boost::apply_visitor(visitor_ref
, v2
) == "10");
223 #ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
224 std::string
& ref_to_string
= boost::apply_visitor(visitor_ref
, v1
);
225 BOOST_TEST(ref_to_string
== "1");
227 lex_streamer_void lex_streamer_void_visitor
;
228 boost::apply_visitor(lex_streamer_void(), v1
);
229 boost::apply_visitor(lex_streamer_void(), v2
);
230 #ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
231 boost::apply_visitor(lex_streamer_void_visitor
)(v2
);
234 boost::ignore_unused(lex_streamer_visitor
, visitor_ref
, lex_streamer_void_visitor
);
239 template <class T1
, class T2
>
240 std::string
operator()(const T1
& v1
, const T2
& v2
) const {
241 return boost::lexical_cast
<std::string
>(v1
) + "+" + boost::lexical_cast
<std::string
>(v2
);
245 template <class T1
, class T2
, class T3
>
246 std::string
operator()(const T1
& v1
, const T2
& v2
, const T3
& v3
) const {
247 return boost::lexical_cast
<std::string
>(v1
) + "+"
248 + boost::lexical_cast
<std::string
>(v2
) + '+'
249 + boost::lexical_cast
<std::string
>(v3
);
255 typedef boost::variant
<int, std::string
, double> variant_type
;
256 variant_type
v1(1), v2("10"), v3(100.0);
257 lex_combine lex_combine_visitor
;
259 BOOST_TEST(boost::apply_visitor(lex_combine(), v1
, v2
) == "1+10");
260 BOOST_TEST(boost::apply_visitor(lex_combine(), v2
, v1
) == "10+1");
261 BOOST_TEST_IF_HAS_VARIADIC(boost::apply_visitor(lex_combine_visitor
)(v2
, v1
) == "10+1");
264 #ifndef BOOST_NO_CXX14_GENERIC_LAMBDAS
266 boost::apply_visitor(
267 [](auto v1
, auto v2
) {
268 return boost::lexical_cast
<std::string
>(v1
) + "+"
269 + boost::lexical_cast
<std::string
>(v2
);
276 boost::apply_visitor(
277 [](auto v1
, auto v2
) {
278 return boost::lexical_cast
<std::string
>(v1
) + "+"
279 + boost::lexical_cast
<std::string
>(v2
);
286 boost::apply_visitor([](auto v1
, auto v2
) { std::cout
<< v1
<< '+' << v2
<< std::endl
; }, v1
, v2
);
287 boost::apply_visitor([](auto v1
, auto v2
) { std::cout
<< v1
<< '+' << v2
<< std::endl
; }, v2
, v1
);
291 lex_streamer2 visitor_ref
;
292 BOOST_TEST(boost::apply_visitor(visitor_ref
, v1
, v2
) == "1+10");
293 BOOST_TEST(boost::apply_visitor(visitor_ref
, v2
, v1
) == "10+1");
294 #ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
295 std::string
& ref_to_string
= boost::apply_visitor(visitor_ref
)(v1
, v2
);
296 BOOST_TEST(ref_to_string
== "1+10");
299 boost::apply_visitor(lex_streamer_void(), v1
, v2
);
300 boost::apply_visitor(lex_streamer_void(), v2
, v1
);
302 boost::ignore_unused(lex_combine_visitor
, visitor_ref
);
305 #undef BOOST_TEST_IF_HAS_VARIADIC
309 #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
310 typedef boost::variant
<int, std::string
, double> variant_type
;
311 variant_type
v1(1), v2("10"), v3(100);
312 lex_combine lex_combine_visitor
;
314 BOOST_TEST(boost::apply_visitor(lex_combine(), v1
, v2
, v3
) == "1+10+100");
315 BOOST_TEST(boost::apply_visitor(lex_combine(), v2
, v1
, v3
) == "10+1+100");
316 BOOST_TEST(boost::apply_visitor(lex_combine_visitor
)(v2
, v1
, v3
) == "10+1+100");
319 #ifndef BOOST_NO_CXX14_GENERIC_LAMBDAS
321 boost::apply_visitor(
322 [](auto v1
, auto v2
, auto v3
) {
323 return boost::lexical_cast
<std::string
>(v1
) + "+"
324 + boost::lexical_cast
<std::string
>(v2
) + "+"
325 + boost::lexical_cast
<std::string
>(v3
);
333 boost::apply_visitor(
334 [](auto v1
, auto v2
, auto v3
) {
335 return boost::lexical_cast
<std::string
>(v1
) + "+"
336 + boost::lexical_cast
<std::string
>(v2
) + "+"
337 + boost::lexical_cast
<std::string
>(v3
);
345 boost::apply_visitor(
346 [](auto v1
, auto v2
, auto v3
) { std::cout
<< v1
<< '+' << v2
<< '+' << v3
<< std::endl
; },
349 boost::apply_visitor(
350 [](auto v1
, auto v2
, auto v3
) { std::cout
<< v1
<< '+' << v2
<< '+' << v3
<< std::endl
; },
356 lex_streamer2 visitor_ref
;
357 BOOST_TEST(boost::apply_visitor(visitor_ref
, v1
, v2
) == "1+10");
358 BOOST_TEST(boost::apply_visitor(visitor_ref
)(v2
, v1
) == "10+1");
359 std::string
& ref_to_string
= boost::apply_visitor(visitor_ref
, v1
, v2
);
360 BOOST_TEST(ref_to_string
== "1+10");
362 lex_streamer_void lex_streamer_void_visitor
;
363 boost::apply_visitor(lex_streamer_void(), v1
, v2
, v1
);
364 boost::apply_visitor(lex_streamer_void(), v2
, v1
, v1
);
365 boost::apply_visitor(lex_streamer_void_visitor
)(v2
, v1
, v1
);
366 #endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
377 test_has_result_type_triat();
379 return boost::report_errors();