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