1 //-----------------------------------------------------------------------------
2 // boost-libs variant/test/variant_visit_test.cpp source file
3 // See http://www.boost.org for updates, documentation, and revision history.
4 //-----------------------------------------------------------------------------
5 //
6 // Copyright (c) 2003
7 // Eric Friedman
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 #include "boost/variant/variant.hpp"
14 #include "boost/variant/apply_visitor.hpp"
15 #include "boost/variant/static_visitor.hpp"
16 #include "boost/core/lightweight_test.hpp"
17
18 #include "boost/mpl/bool.hpp"
19 #include "boost/mpl/and.hpp"
20 #include "boost/type_traits/is_same.hpp"
21
22 struct udt1
23 {
24 };
25
26 struct udt2
27 {
28 };
29
30 template <typename T>
31 class unary_check_content_type
32 : public boost::static_visitor<bool>
33 {
34 public:
35
36 // not recommended design, but simplifies workarounds:
37
38 template <typename U>
operator ()(U &) const39 bool operator()(U&) const
40 {
41 return ::boost::is_same<T,U>::value;
42 }
43
44 };
45
46 template <typename T1, typename T2>
47 class binary_check_content_type
48 : public boost::static_visitor<bool>
49 {
50 public:
51
52 // not recommended design, but simplifies workarounds:
53
54 template <typename U1, typename U2>
operator ()(U1 &,U2 &) const55 bool operator()(U1&, U2&) const
56 {
57 return ::boost::mpl::and_<
58 boost::is_same<T1,U1>
59 , boost::is_same<T2,U2>
60 >::value;
61 }
62
63 };
64
65 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS // BOOST_NO_CXX11_RVALUE_REFERENCES is not enough for disabling buggy GCCs < 4.8
66 struct rvalue_ref_visitor
67 {
68 typedef int result_type;
operator ()rvalue_ref_visitor69 int operator()(udt1&&) const { return 0; }
operator ()rvalue_ref_visitor70 int operator()(udt2&&) const { return 1; }
71 };
72 #endif
73 #ifdef BOOST_VARIANT_HAS_DECLTYPE_APPLY_VISITOR_RETURN_TYPE
74 struct rvalue_ref_decltype_visitor
75 {
operator ()rvalue_ref_decltype_visitor76 int operator()(udt1&&) const { return 0; }
operator ()rvalue_ref_decltype_visitor77 int operator()(udt2&&) const { return 1; }
78 };
79 #endif
80
81 template <typename Checker, typename Variant>
unary_test(Variant & var,Checker * =0)82 inline void unary_test(Variant& var, Checker* = 0)
83 {
84 Checker checker;
85 const Checker& const_checker = checker;
86
87 // standard tests
88
89 BOOST_TEST( boost::apply_visitor(checker, var) );
90 BOOST_TEST( boost::apply_visitor(const_checker, var) );
91 BOOST_TEST( boost::apply_visitor(Checker(), var) );
92
93 // delayed tests
94
95 BOOST_TEST( boost::apply_visitor(checker)(var) );
96 BOOST_TEST( boost::apply_visitor(const_checker)(var) );
97 }
98
99 template <typename Checker, typename Variant1, typename Variant2>
binary_test(Variant1 & var1,Variant2 & var2,Checker * =0)100 inline void binary_test(Variant1& var1, Variant2& var2, Checker* = 0)
101 {
102 Checker checker;
103 const Checker& const_checker = checker;
104
105 // standard tests
106
107 BOOST_TEST( boost::apply_visitor(checker, var1, var2) );
108 BOOST_TEST( boost::apply_visitor(const_checker, var1, var2) );
109 BOOST_TEST( boost::apply_visitor(Checker(), var1, var2) );
110
111 // delayed tests
112
113 BOOST_TEST( boost::apply_visitor(checker)(var1, var2) );
114 BOOST_TEST( boost::apply_visitor(const_checker)(var1, var2) );
115 }
116
main()117 int main()
118 {
119 typedef boost::variant<udt1,udt2> var_t;
120 udt1 u1;
121 var_t var1(u1);
122 udt2 u2;
123 var_t var2(u2);
124
125 const var_t& cvar1 = var1;
126 const var_t& cvar2 = var2;
127
128 //
129 // unary tests
130 //
131
132 typedef unary_check_content_type<udt1> check1_t;
133 typedef unary_check_content_type<const udt1> check1_const_t;
134 typedef unary_check_content_type<udt2> check2_t;
135 typedef unary_check_content_type<const udt2> check2_const_t;
136
137 unary_test< check1_t >(var1);
138 unary_test< check1_const_t >(cvar1);
139
140 unary_test< check2_t >(var2);
141 unary_test< check2_const_t >(cvar2);
142
143 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS // BOOST_NO_CXX11_RVALUE_REFERENCES is not enough for disabling buggy GCCs < 4.8
144 BOOST_TEST_EQ( (boost::apply_visitor(
145 rvalue_ref_visitor(),
146 boost::variant<udt1, udt2>(udt2()))), 1 );
147 #endif
148 #ifdef BOOST_VARIANT_HAS_DECLTYPE_APPLY_VISITOR_RETURN_TYPE
149 BOOST_TEST_EQ( (boost::apply_visitor(
150 rvalue_ref_decltype_visitor(),
151 boost::variant<udt1, udt2>(udt2()))), 1 );
152 #endif
153
154 //
155 // binary tests
156 //
157
158 typedef binary_check_content_type<udt1,udt2> check12_t;
159 typedef binary_check_content_type<const udt1, const udt2> check12_const_t;
160 typedef binary_check_content_type<udt2,udt1> check21_t;
161 typedef binary_check_content_type<const udt2, const udt1> check21_const_t;
162
163 binary_test< check12_t >(var1,var2);
164 binary_test< check12_const_t >(cvar1,cvar2);
165
166 binary_test< check21_t >(var2,var1);
167 binary_test< check21_const_t >(cvar2,cvar1);
168
169 return boost::report_errors();
170 }
171