1 //-----------------------------------------------------------------------------
2 // boost-libs variant/test/variant_get_test.cpp source file
3 // See http://www.boost.org for updates, documentation, and revision history.
4 //-----------------------------------------------------------------------------
6 // Copyright (c) 2014-2015 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/variant/get.hpp"
13 #include "boost/variant/variant.hpp"
14 #include "boost/variant/polymorphic_get.hpp"
15 #include "boost/variant/recursive_wrapper.hpp"
16 #include "boost/test/minimal.hpp"
21 base() : trash(123) {}
22 base(const base
& b
) : trash(b
.trash
) { int i
= 100; (void)i
; }
23 const base
& operator=(const base
& b
) {
33 struct derived1
: base
{};
34 struct derived2
: base
{};
36 struct vbase
{ short trash
; virtual ~vbase(){} virtual int foo() const { return 0; } };
37 struct vderived1
: virtual vbase
{ virtual int foo() const { return 1; } };
38 struct vderived2
: virtual vbase
{ virtual int foo() const { return 3; } };
39 struct vderived3
: vderived1
, vderived2
{ virtual int foo() const { return 3; } };
41 typedef boost::variant
<int, base
, derived1
, derived2
, std::string
> var_t
;
42 typedef boost::variant
<int, derived1
, derived2
, std::string
> var_t_shortened
;
43 typedef boost::variant
<base
, derived1
, derived2
> var_t_no_fallback
;
44 typedef boost::variant
<int&, base
&, derived1
&, derived2
&, std::string
&> var_ref_t
;
45 typedef boost::variant
<const int&, const base
&, const derived1
&, const derived2
&, const std::string
&> var_cref_t
;
47 struct recursive_structure
;
48 typedef boost::variant
<
49 int, base
, derived1
, derived2
, std::string
, boost::recursive_wrapper
<recursive_structure
>
51 struct recursive_structure
{ var_req_t var
; };
53 template <class T
, class V
, class TestType
>
54 inline void check_polymorphic_get_on_types_impl_single_type(V
* v
)
56 typedef typename
boost::add_reference
<TestType
>::type ref_test_t
;
57 typedef typename
boost::add_reference
<const TestType
>::type cref_test_t
;
58 const bool exact_same
= !!boost::is_same
<T
, TestType
>::value
;
59 const bool ref_same
= !!boost::is_same
<T
, ref_test_t
>::value
;
61 if (exact_same
|| ref_same
) {
62 BOOST_CHECK(boost::polymorphic_get
<TestType
>(v
));
63 BOOST_CHECK(boost::polymorphic_get
<const TestType
>(v
));
64 BOOST_CHECK(boost::polymorphic_strict_get
<TestType
>(v
));
65 BOOST_CHECK(boost::polymorphic_strict_get
<const TestType
>(v
));
66 BOOST_CHECK(boost::polymorphic_relaxed_get
<TestType
>(v
));
67 BOOST_CHECK(boost::polymorphic_relaxed_get
<const TestType
>(v
));
70 BOOST_CHECK(boost::polymorphic_get
<ref_test_t
>(v
));
71 BOOST_CHECK(boost::polymorphic_get
<cref_test_t
>(v
));
72 BOOST_CHECK(boost::polymorphic_strict_get
<ref_test_t
>(v
));
73 BOOST_CHECK(boost::polymorphic_strict_get
<cref_test_t
>(v
));
74 BOOST_CHECK(boost::polymorphic_relaxed_get
<ref_test_t
>(v
));
75 BOOST_CHECK(boost::polymorphic_relaxed_get
<cref_test_t
>(v
));
78 BOOST_CHECK(!boost::polymorphic_get
<TestType
>(v
));
79 BOOST_CHECK(!boost::polymorphic_get
<const TestType
>(v
));
80 BOOST_CHECK(!boost::polymorphic_strict_get
<TestType
>(v
));
81 BOOST_CHECK(!boost::polymorphic_strict_get
<const TestType
>(v
));
82 BOOST_CHECK(!boost::polymorphic_relaxed_get
<TestType
>(v
));
83 BOOST_CHECK(!boost::polymorphic_relaxed_get
<const TestType
>(v
));
87 template <class T
, class V
, class TestType
>
88 inline void check_get_on_types_impl_single_type(V
* v
)
90 typedef typename
boost::add_reference
<TestType
>::type ref_test_t
;
91 typedef typename
boost::add_reference
<const TestType
>::type cref_test_t
;
92 const bool exact_same
= !!boost::is_same
<T
, TestType
>::value
;
93 const bool ref_same
= !!boost::is_same
<T
, ref_test_t
>::value
;
95 if (exact_same
|| ref_same
) {
96 BOOST_CHECK(boost::get
<TestType
>(v
));
97 BOOST_CHECK(boost::get
<const TestType
>(v
));
98 BOOST_CHECK(boost::strict_get
<TestType
>(v
));
99 BOOST_CHECK(boost::strict_get
<const TestType
>(v
));
100 BOOST_CHECK(boost::relaxed_get
<TestType
>(v
));
101 BOOST_CHECK(boost::relaxed_get
<const TestType
>(v
));
103 BOOST_CHECK(boost::get
<cref_test_t
>(v
));
104 BOOST_CHECK(boost::strict_get
<cref_test_t
>(v
));
105 BOOST_CHECK(boost::relaxed_get
<cref_test_t
>(v
));
108 BOOST_CHECK(boost::get
<ref_test_t
>(v
));
109 BOOST_CHECK(boost::get
<cref_test_t
>(v
));
110 BOOST_CHECK(boost::strict_get
<ref_test_t
>(v
));
111 BOOST_CHECK(boost::strict_get
<cref_test_t
>(v
));
112 BOOST_CHECK(boost::relaxed_get
<ref_test_t
>(v
));
113 BOOST_CHECK(boost::relaxed_get
<cref_test_t
>(v
));
116 BOOST_CHECK(!boost::get
<TestType
>(v
));
117 BOOST_CHECK(!boost::get
<const TestType
>(v
));
118 BOOST_CHECK(!boost::strict_get
<TestType
>(v
));
119 BOOST_CHECK(!boost::strict_get
<const TestType
>(v
));
120 BOOST_CHECK(!boost::relaxed_get
<TestType
>(v
));
121 BOOST_CHECK(!boost::relaxed_get
<const TestType
>(v
));
125 template <class T
, class V
>
126 inline void check_get_on_types_impl(V
* v
)
128 check_get_on_types_impl_single_type
<T
, V
, int>(v
);
129 check_polymorphic_get_on_types_impl_single_type
<T
, V
, int>(v
);
131 check_get_on_types_impl_single_type
<T
, V
, base
>(v
);
133 check_get_on_types_impl_single_type
<T
, V
, derived1
>(v
);
134 check_polymorphic_get_on_types_impl_single_type
<T
, V
, derived1
>(v
);
136 check_get_on_types_impl_single_type
<T
, V
, derived2
>(v
);
137 check_polymorphic_get_on_types_impl_single_type
<T
, V
, derived2
>(v
);
139 check_get_on_types_impl_single_type
<T
, V
, std::string
>(v
);
140 check_polymorphic_get_on_types_impl_single_type
<T
, V
, std::string
>(v
);
142 // Never exist in here
143 BOOST_CHECK(!boost::relaxed_get
<short>(v
));
144 BOOST_CHECK(!boost::relaxed_get
<const short>(v
));
145 BOOST_CHECK(!boost::relaxed_get
<char>(v
));
146 BOOST_CHECK(!boost::relaxed_get
<char*>(v
));
147 BOOST_CHECK(!boost::relaxed_get
<bool>(v
));
148 BOOST_CHECK(!boost::relaxed_get
<const bool>(v
));
150 BOOST_CHECK(!boost::polymorphic_relaxed_get
<short>(v
));
151 BOOST_CHECK(!boost::polymorphic_relaxed_get
<const short>(v
));
152 BOOST_CHECK(!boost::polymorphic_relaxed_get
<char>(v
));
153 BOOST_CHECK(!boost::polymorphic_relaxed_get
<char*>(v
));
154 BOOST_CHECK(!boost::polymorphic_relaxed_get
<bool>(v
));
155 BOOST_CHECK(!boost::polymorphic_relaxed_get
<const bool>(v
));
157 boost::get
<T
>(*v
); // Must compile
158 boost::get
<const T
>(*v
); // Must compile
159 boost::strict_get
<T
>(*v
); // Must compile
160 boost::strict_get
<const T
>(*v
); // Must compile
162 boost::polymorphic_get
<T
>(*v
); // Must compile
163 boost::polymorphic_get
<const T
>(*v
); // Must compile
164 boost::polymorphic_strict_get
<T
>(*v
); // Must compile
165 boost::polymorphic_strict_get
<const T
>(*v
); // Must compile
168 template <class T
, class V
>
169 inline void check_get_on_types(V
* v
)
171 check_get_on_types_impl
<T
, V
>(v
);
172 check_get_on_types_impl
<T
, const V
>(v
);
175 inline void get_test()
178 check_get_on_types
<int>(&v
);
180 var_t(base()).swap(v
);
181 check_get_on_types
<base
>(&v
);
183 var_t(derived1()).swap(v
);
184 check_get_on_types
<derived1
>(&v
);
186 var_t(derived2()).swap(v
);
187 check_get_on_types
<derived2
>(&v
);
189 var_t(std::string("Hello")).swap(v
);
190 check_get_on_types
<std::string
>(&v
);
192 var_t_shortened vs
= derived2();
193 check_polymorphic_get_on_types_impl_single_type
<derived2
, var_t_shortened
, int>(&vs
);
194 check_polymorphic_get_on_types_impl_single_type
<derived2
, const var_t_shortened
, int>(&vs
);
195 // Checking that Base is really determinated
196 check_polymorphic_get_on_types_impl_single_type
<base
, var_t_shortened
, base
>(&vs
);
197 check_polymorphic_get_on_types_impl_single_type
<base
, const var_t_shortened
, base
>(&vs
);
200 check_polymorphic_get_on_types_impl_single_type
<derived2
, var_t_shortened
, int>(&vs
);
201 check_polymorphic_get_on_types_impl_single_type
<derived2
, const var_t_shortened
, int>(&vs
);
202 // Checking that Base is really determinated
203 check_polymorphic_get_on_types_impl_single_type
<base
, var_t_shortened
, base
>(&vs
);
204 check_polymorphic_get_on_types_impl_single_type
<base
, const var_t_shortened
, base
>(&vs
);
207 inline void get_test_no_fallback()
210 var_t_no_fallback(base()).swap(v
);
211 check_polymorphic_get_on_types_impl_single_type
<base
, var_t_no_fallback
, base
>(&v
);
212 check_polymorphic_get_on_types_impl_single_type
<base
, const var_t_no_fallback
, base
>(&v
);
213 check_get_on_types_impl_single_type
<base
, var_t_no_fallback
, base
>(&v
);
214 check_get_on_types_impl_single_type
<base
, const var_t_no_fallback
, base
>(&v
);
216 var_t_no_fallback(derived1()).swap(v
);
217 check_polymorphic_get_on_types_impl_single_type
<base
, var_t_no_fallback
, base
>(&v
);
218 check_polymorphic_get_on_types_impl_single_type
<base
, const var_t_no_fallback
, base
>(&v
);
219 check_get_on_types_impl_single_type
<derived1
, var_t_no_fallback
, derived1
>(&v
);
220 check_get_on_types_impl_single_type
<derived1
, const var_t_no_fallback
, derived1
>(&v
);
222 var_t_no_fallback(derived2()).swap(v
);
223 check_polymorphic_get_on_types_impl_single_type
<base
, var_t_no_fallback
, base
>(&v
);
224 check_polymorphic_get_on_types_impl_single_type
<base
, const var_t_no_fallback
, base
>(&v
);
225 check_get_on_types_impl_single_type
<derived2
, var_t_no_fallback
, derived2
>(&v
);
226 check_get_on_types_impl_single_type
<derived2
, const var_t_no_fallback
, derived2
>(&v
);
229 inline void get_ref_test()
233 check_get_on_types
<int>(&v
);
237 check_get_on_types
<base
>(&v1
);
241 check_get_on_types
<derived1
>(&v2
);
245 check_get_on_types
<derived2
>(&v3
);
247 std::string
s("Hello");
249 check_get_on_types
<std::string
>(&v4
);
253 inline void get_cref_test()
257 BOOST_CHECK(boost::get
<const int>(&v
));
258 BOOST_CHECK(!boost::get
<const base
>(&v
));
262 BOOST_CHECK(boost::get
<const base
>(&v1
));
263 BOOST_CHECK(!boost::get
<const derived1
>(&v1
));
264 BOOST_CHECK(!boost::get
<const int>(&v1
));
266 std::string
s("Hello");
267 const var_cref_t v4
= s
;
268 BOOST_CHECK(boost::get
<const std::string
>(&v4
));
269 BOOST_CHECK(!boost::get
<const int>(&v4
));
272 inline void get_recursive_test()
275 check_get_on_types
<int>(&v
);
277 var_req_t(base()).swap(v
);
278 check_get_on_types
<base
>(&v
);
280 var_req_t(derived1()).swap(v
);
281 check_get_on_types
<derived1
>(&v
);
283 var_req_t(derived2()).swap(v
);
284 check_get_on_types
<derived2
>(&v
);
286 var_req_t(std::string("Hello")).swap(v
);
287 check_get_on_types
<std::string
>(&v
);
289 recursive_structure s
= { v
}; // copying "v"
291 check_get_on_types
<recursive_structure
>(&v
);
295 inline void check_that_does_not_exist_impl()
297 using namespace boost::detail::variant
;
299 BOOST_CHECK((holds_element
<T
, const int>::value
));
300 BOOST_CHECK((!holds_element
<T
, short>::value
));
301 BOOST_CHECK((!holds_element
<T
, short>::value
));
302 BOOST_CHECK((!holds_element
<T
, const short>::value
));
303 BOOST_CHECK((!holds_element
<T
, char*>::value
));
304 BOOST_CHECK((!holds_element
<T
, const char*>::value
));
305 BOOST_CHECK((!holds_element
<T
, char[5]>::value
));
306 BOOST_CHECK((!holds_element
<T
, const char[5]>::value
));
307 BOOST_CHECK((!holds_element
<T
, bool>::value
));
308 BOOST_CHECK((!holds_element
<T
, const bool>::value
));
310 BOOST_CHECK((!holds_element
<T
, boost::recursive_wrapper
<int> >::value
));
311 BOOST_CHECK((!holds_element
<T
, boost::recursive_wrapper
<short> >::value
));
312 BOOST_CHECK((!holds_element
<T
, boost::detail::reference_content
<short> >::value
));
315 BOOST_CHECK((holds_element_polymorphic
<T
, const int>::value
));
316 BOOST_CHECK((!holds_element_polymorphic
<T
, short>::value
));
317 BOOST_CHECK((!holds_element_polymorphic
<T
, short>::value
));
318 BOOST_CHECK((!holds_element_polymorphic
<T
, const short>::value
));
319 BOOST_CHECK((!holds_element_polymorphic
<T
, char*>::value
));
320 BOOST_CHECK((!holds_element_polymorphic
<T
, const char*>::value
));
321 BOOST_CHECK((!holds_element_polymorphic
<T
, char[5]>::value
));
322 BOOST_CHECK((!holds_element_polymorphic
<T
, const char[5]>::value
));
323 BOOST_CHECK((!holds_element_polymorphic
<T
, bool>::value
));
324 BOOST_CHECK((!holds_element_polymorphic
<T
, const bool>::value
));
326 BOOST_CHECK((!holds_element_polymorphic
<T
, boost::recursive_wrapper
<int> >::value
));
327 BOOST_CHECK((!holds_element_polymorphic
<T
, boost::recursive_wrapper
<short> >::value
));
328 BOOST_CHECK((!holds_element_polymorphic
<T
, boost::detail::reference_content
<short> >::value
));
331 inline void check_that_does_not_exist()
333 using namespace boost::detail::variant
;
335 BOOST_CHECK((holds_element
<var_t
, int>::value
));
336 BOOST_CHECK((holds_element
<var_ref_t
, int>::value
));
337 BOOST_CHECK((!holds_element
<var_cref_t
, int>::value
));
339 check_that_does_not_exist_impl
<var_t
>();
340 check_that_does_not_exist_impl
<var_ref_t
>();
341 check_that_does_not_exist_impl
<var_cref_t
>();
342 check_that_does_not_exist_impl
<var_req_t
>();
345 int test_main(int , char* [])
348 get_test_no_fallback();
351 get_recursive_test();
352 check_that_does_not_exist();
354 return boost::exit_success
;