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-2022 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)
13 #pragma warning(disable: 4127) // conditional expression is constant
14 #pragma warning(disable: 4181) // qualifier applied to reference type; ignored
17 #include "boost/variant/get.hpp"
18 #include "boost/variant/variant.hpp"
19 #include "boost/variant/polymorphic_get.hpp"
20 #include "boost/variant/recursive_wrapper.hpp"
21 #include "boost/core/lightweight_test.hpp"
26 base() : trash(123) {}
27 base(const base
& b
) : trash(b
.trash
) { int i
= 100; (void)i
; }
28 const base
& operator=(const base
& b
) {
38 struct derived1
: base
{};
39 struct derived2
: base
{};
41 struct vbase
{ short trash
; virtual ~vbase(){} virtual int foo() const { return 0; } };
42 struct vderived1
: virtual vbase
{ virtual int foo() const { return 1; } };
43 struct vderived2
: virtual vbase
{ virtual int foo() const { return 3; } };
44 struct vderived3
: vderived1
, vderived2
{ virtual int foo() const { return 3; } };
46 typedef boost::variant
<int, base
, derived1
, derived2
, std::string
> var_t
;
47 typedef boost::variant
<int, derived1
, derived2
, std::string
> var_t_shortened
;
48 typedef boost::variant
<base
, derived1
, derived2
> var_t_no_fallback
;
49 typedef boost::variant
<int&, base
&, derived1
&, derived2
&, std::string
&> var_ref_t
;
50 typedef boost::variant
<const int&, const base
&, const derived1
&, const derived2
&, const std::string
&> var_cref_t
;
52 struct recursive_structure
;
53 typedef boost::variant
<
54 int, base
, derived1
, derived2
, std::string
, boost::recursive_wrapper
<recursive_structure
>
56 struct recursive_structure
{ var_req_t var
; };
58 template <class TypeInVariant
, class V
, class TestType
>
59 inline void check_polymorphic_get_on_types_impl_single_type(V
* v
)
61 typedef typename
boost::add_reference
<TestType
>::type ref_test_t
;
62 typedef typename
boost::add_reference
<const TestType
>::type cref_test_t
;
63 const bool exact_same
= !!boost::is_same
<TypeInVariant
, TestType
>::value
;
64 const bool ref_same
= !!boost::is_same
<TypeInVariant
, ref_test_t
>::value
;
66 if (exact_same
|| ref_same
) {
67 BOOST_TEST(boost::polymorphic_get
<TestType
>(v
));
68 BOOST_TEST(boost::polymorphic_get
<const TestType
>(v
));
69 BOOST_TEST(boost::polymorphic_strict_get
<TestType
>(v
));
70 BOOST_TEST(boost::polymorphic_strict_get
<const TestType
>(v
));
71 BOOST_TEST(boost::polymorphic_relaxed_get
<TestType
>(v
));
72 BOOST_TEST(boost::polymorphic_relaxed_get
<const TestType
>(v
));
74 BOOST_TEST(boost::polymorphic_get
<cref_test_t
>(v
));
75 BOOST_TEST(boost::polymorphic_strict_get
<cref_test_t
>(v
));
76 BOOST_TEST(boost::polymorphic_relaxed_get
<cref_test_t
>(v
));
79 BOOST_TEST(boost::polymorphic_get
<ref_test_t
>(v
));
80 BOOST_TEST(boost::polymorphic_get
<cref_test_t
>(v
));
81 BOOST_TEST(boost::polymorphic_strict_get
<ref_test_t
>(v
));
82 BOOST_TEST(boost::polymorphic_strict_get
<cref_test_t
>(v
));
83 BOOST_TEST(boost::polymorphic_relaxed_get
<ref_test_t
>(v
));
84 BOOST_TEST(boost::polymorphic_relaxed_get
<cref_test_t
>(v
));
87 BOOST_TEST(!boost::polymorphic_get
<TestType
>(v
));
88 BOOST_TEST(!boost::polymorphic_get
<const TestType
>(v
));
89 BOOST_TEST(!boost::polymorphic_strict_get
<TestType
>(v
));
90 BOOST_TEST(!boost::polymorphic_strict_get
<const TestType
>(v
));
91 BOOST_TEST(!boost::polymorphic_relaxed_get
<TestType
>(v
));
92 BOOST_TEST(!boost::polymorphic_relaxed_get
<const TestType
>(v
));
96 template <class T
, class V
, class TestType
>
97 inline void check_get_on_types_impl_single_type(V
* v
)
99 typedef typename
boost::add_reference
<TestType
>::type ref_test_t
;
100 typedef typename
boost::add_reference
<const TestType
>::type cref_test_t
;
101 const bool exact_same
= !!boost::is_same
<T
, TestType
>::value
;
102 const bool ref_same
= !!boost::is_same
<T
, ref_test_t
>::value
;
104 if (exact_same
|| ref_same
) {
105 BOOST_TEST(boost::get
<TestType
>(v
));
106 BOOST_TEST(boost::get
<const TestType
>(v
));
107 BOOST_TEST(boost::strict_get
<TestType
>(v
));
108 BOOST_TEST(boost::strict_get
<const TestType
>(v
));
109 BOOST_TEST(boost::relaxed_get
<TestType
>(v
));
110 BOOST_TEST(boost::relaxed_get
<const TestType
>(v
));
112 BOOST_TEST(boost::get
<cref_test_t
>(v
));
113 BOOST_TEST(boost::strict_get
<cref_test_t
>(v
));
114 BOOST_TEST(boost::relaxed_get
<cref_test_t
>(v
));
117 BOOST_TEST(boost::get
<ref_test_t
>(v
));
118 BOOST_TEST(boost::get
<cref_test_t
>(v
));
119 BOOST_TEST(boost::strict_get
<ref_test_t
>(v
));
120 BOOST_TEST(boost::strict_get
<cref_test_t
>(v
));
121 BOOST_TEST(boost::relaxed_get
<ref_test_t
>(v
));
122 BOOST_TEST(boost::relaxed_get
<cref_test_t
>(v
));
125 BOOST_TEST(!boost::get
<TestType
>(v
));
126 BOOST_TEST(!boost::get
<const TestType
>(v
));
127 BOOST_TEST(!boost::strict_get
<TestType
>(v
));
128 BOOST_TEST(!boost::strict_get
<const TestType
>(v
));
129 BOOST_TEST(!boost::relaxed_get
<TestType
>(v
));
130 BOOST_TEST(!boost::relaxed_get
<const TestType
>(v
));
134 template <class T
, class V
>
135 inline void check_get_on_types_impl(V
* v
)
137 check_get_on_types_impl_single_type
<T
, V
, int>(v
);
138 check_polymorphic_get_on_types_impl_single_type
<T
, V
, int>(v
);
140 check_get_on_types_impl_single_type
<T
, V
, base
>(v
);
142 check_get_on_types_impl_single_type
<T
, V
, derived1
>(v
);
143 check_polymorphic_get_on_types_impl_single_type
<T
, V
, derived1
>(v
);
145 check_get_on_types_impl_single_type
<T
, V
, derived2
>(v
);
146 check_polymorphic_get_on_types_impl_single_type
<T
, V
, derived2
>(v
);
148 check_get_on_types_impl_single_type
<T
, V
, std::string
>(v
);
149 check_polymorphic_get_on_types_impl_single_type
<T
, V
, std::string
>(v
);
151 // Never exist in here
152 BOOST_TEST(!boost::relaxed_get
<short>(v
));
153 BOOST_TEST(!boost::relaxed_get
<const short>(v
));
154 BOOST_TEST(!boost::relaxed_get
<char>(v
));
155 BOOST_TEST(!boost::relaxed_get
<char*>(v
));
156 BOOST_TEST(!boost::relaxed_get
<bool>(v
));
157 BOOST_TEST(!boost::relaxed_get
<const bool>(v
));
159 BOOST_TEST(!boost::polymorphic_relaxed_get
<short>(v
));
160 BOOST_TEST(!boost::polymorphic_relaxed_get
<const short>(v
));
161 BOOST_TEST(!boost::polymorphic_relaxed_get
<char>(v
));
162 BOOST_TEST(!boost::polymorphic_relaxed_get
<char*>(v
));
163 BOOST_TEST(!boost::polymorphic_relaxed_get
<bool>(v
));
164 BOOST_TEST(!boost::polymorphic_relaxed_get
<const bool>(v
));
166 boost::get
<T
>(*v
); // Must compile
167 boost::get
<const T
>(*v
); // Must compile
168 boost::strict_get
<T
>(*v
); // Must compile
169 boost::strict_get
<const T
>(*v
); // Must compile
171 bool is_ref
= boost::is_lvalue_reference
<T
>::value
;
174 boost::polymorphic_get
<T
>(*v
); // Must compile
175 boost::polymorphic_get
<const T
>(*v
); // Must compile
176 boost::polymorphic_strict_get
<T
>(*v
); // Must compile
177 boost::polymorphic_strict_get
<const T
>(*v
); // Must compile
181 template <class T
, class V
>
182 inline void check_get_on_types(V
* v
)
184 check_get_on_types_impl
<T
, V
>(v
);
185 check_get_on_types_impl
<T
, const V
>(v
);
188 inline void get_test()
191 check_get_on_types
<int>(&v
);
193 var_t(base()).swap(v
);
194 check_get_on_types
<base
>(&v
);
196 var_t(derived1()).swap(v
);
197 check_get_on_types
<derived1
>(&v
);
199 var_t(derived2()).swap(v
);
200 check_get_on_types
<derived2
>(&v
);
202 var_t(std::string("Hello")).swap(v
);
203 check_get_on_types
<std::string
>(&v
);
205 var_t_shortened vs
= derived2();
206 check_polymorphic_get_on_types_impl_single_type
<derived2
, var_t_shortened
, int>(&vs
);
207 check_polymorphic_get_on_types_impl_single_type
<derived2
, const var_t_shortened
, int>(&vs
);
208 // Checking that Base is really determinated
209 check_polymorphic_get_on_types_impl_single_type
<base
, var_t_shortened
, base
>(&vs
);
210 check_polymorphic_get_on_types_impl_single_type
<base
, const var_t_shortened
, base
>(&vs
);
213 check_polymorphic_get_on_types_impl_single_type
<derived2
, var_t_shortened
, int>(&vs
);
214 check_polymorphic_get_on_types_impl_single_type
<derived2
, const var_t_shortened
, int>(&vs
);
215 // Checking that Base is really determinated
216 check_polymorphic_get_on_types_impl_single_type
<base
, var_t_shortened
, base
>(&vs
);
217 check_polymorphic_get_on_types_impl_single_type
<base
, const var_t_shortened
, base
>(&vs
);
220 inline void get_test_no_fallback()
223 var_t_no_fallback(base()).swap(v
);
224 check_polymorphic_get_on_types_impl_single_type
<base
, var_t_no_fallback
, base
>(&v
);
225 check_polymorphic_get_on_types_impl_single_type
<base
, const var_t_no_fallback
, base
>(&v
);
226 check_get_on_types_impl_single_type
<base
, var_t_no_fallback
, base
>(&v
);
227 check_get_on_types_impl_single_type
<base
, const var_t_no_fallback
, base
>(&v
);
229 var_t_no_fallback(derived1()).swap(v
);
230 check_polymorphic_get_on_types_impl_single_type
<base
, var_t_no_fallback
, base
>(&v
);
231 check_polymorphic_get_on_types_impl_single_type
<base
, const var_t_no_fallback
, base
>(&v
);
232 check_get_on_types_impl_single_type
<derived1
, var_t_no_fallback
, derived1
>(&v
);
233 check_get_on_types_impl_single_type
<derived1
, const var_t_no_fallback
, derived1
>(&v
);
235 var_t_no_fallback(derived2()).swap(v
);
236 check_polymorphic_get_on_types_impl_single_type
<base
, var_t_no_fallback
, base
>(&v
);
237 check_polymorphic_get_on_types_impl_single_type
<base
, const var_t_no_fallback
, base
>(&v
);
238 check_get_on_types_impl_single_type
<derived2
, var_t_no_fallback
, derived2
>(&v
);
239 check_get_on_types_impl_single_type
<derived2
, const var_t_no_fallback
, derived2
>(&v
);
242 inline void get_ref_test()
246 check_get_on_types
<int>(&v
);
247 check_get_on_types
<int&>(&v
);
251 check_get_on_types
<base
>(&v1
);
252 check_get_on_types
<base
&>(&v1
);
256 check_get_on_types
<derived1
>(&v2
);
257 check_get_on_types
<derived1
&>(&v2
);
261 check_get_on_types
<derived2
>(&v3
);
262 check_get_on_types
<derived2
&>(&v3
);
264 std::string
s("Hello");
266 check_get_on_types
<std::string
>(&v4
);
267 check_get_on_types
<std::string
&>(&v4
);
271 inline void get_cref_test()
275 BOOST_TEST(boost::get
<const int>(&v
));
276 BOOST_TEST(boost::get
<const int&>(&v
));
277 BOOST_TEST(!boost::get
<const base
>(&v
));
281 BOOST_TEST(boost::get
<const base
>(&v1
));
282 BOOST_TEST(!boost::get
<const derived1
>(&v1
));
283 BOOST_TEST(!boost::get
<const int>(&v1
));
285 std::string
s("Hello");
286 const var_cref_t v4
= s
;
287 BOOST_TEST(boost::get
<const std::string
>(&v4
));
288 BOOST_TEST(!boost::get
<const int>(&v4
));
291 inline void get_recursive_test()
294 check_get_on_types
<int>(&v
);
296 var_req_t(base()).swap(v
);
297 check_get_on_types
<base
>(&v
);
299 var_req_t(derived1()).swap(v
);
300 check_get_on_types
<derived1
>(&v
);
302 var_req_t(derived2()).swap(v
);
303 check_get_on_types
<derived2
>(&v
);
305 var_req_t(std::string("Hello")).swap(v
);
306 check_get_on_types
<std::string
>(&v
);
308 recursive_structure s
= { v
}; // copying "v"
310 check_get_on_types
<recursive_structure
>(&v
);
314 inline void check_that_does_not_exist_impl()
316 using namespace boost::detail::variant
;
318 BOOST_TEST((holds_element
<T
, const int>::value
));
319 BOOST_TEST((!holds_element
<T
, short>::value
));
320 BOOST_TEST((!holds_element
<T
, short>::value
));
321 BOOST_TEST((!holds_element
<T
, const short>::value
));
322 BOOST_TEST((!holds_element
<T
, char*>::value
));
323 BOOST_TEST((!holds_element
<T
, const char*>::value
));
324 BOOST_TEST((!holds_element
<T
, char[5]>::value
));
325 BOOST_TEST((!holds_element
<T
, const char[5]>::value
));
326 BOOST_TEST((!holds_element
<T
, bool>::value
));
327 BOOST_TEST((!holds_element
<T
, const bool>::value
));
329 BOOST_TEST((!holds_element
<T
, boost::recursive_wrapper
<int> >::value
));
330 BOOST_TEST((!holds_element
<T
, boost::recursive_wrapper
<short> >::value
));
331 BOOST_TEST((!holds_element
<T
, boost::detail::reference_content
<short> >::value
));
334 BOOST_TEST((holds_element_polymorphic
<T
, const int>::value
));
335 BOOST_TEST((!holds_element_polymorphic
<T
, short>::value
));
336 BOOST_TEST((!holds_element_polymorphic
<T
, short>::value
));
337 BOOST_TEST((!holds_element_polymorphic
<T
, const short>::value
));
338 BOOST_TEST((!holds_element_polymorphic
<T
, char*>::value
));
339 BOOST_TEST((!holds_element_polymorphic
<T
, const char*>::value
));
340 BOOST_TEST((!holds_element_polymorphic
<T
, char[5]>::value
));
341 BOOST_TEST((!holds_element_polymorphic
<T
, const char[5]>::value
));
342 BOOST_TEST((!holds_element_polymorphic
<T
, bool>::value
));
343 BOOST_TEST((!holds_element_polymorphic
<T
, const bool>::value
));
345 BOOST_TEST((!holds_element_polymorphic
<T
, boost::recursive_wrapper
<int> >::value
));
346 BOOST_TEST((!holds_element_polymorphic
<T
, boost::recursive_wrapper
<short> >::value
));
347 BOOST_TEST((!holds_element_polymorphic
<T
, boost::detail::reference_content
<short> >::value
));
350 inline void check_that_does_not_exist()
352 using namespace boost::detail::variant
;
354 BOOST_TEST((holds_element
<var_t
, int>::value
));
355 BOOST_TEST((holds_element
<var_ref_t
, int>::value
));
356 BOOST_TEST((!holds_element
<var_cref_t
, int>::value
));
358 check_that_does_not_exist_impl
<var_t
>();
359 check_that_does_not_exist_impl
<var_ref_t
>();
360 check_that_does_not_exist_impl
<var_cref_t
>();
361 check_that_does_not_exist_impl
<var_req_t
>();
364 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
370 MoveonlyType(MoveonlyType
&&) {}
371 void operator=(MoveonlyType
&&) {}
374 MoveonlyType(const MoveonlyType
&);
375 void operator=(const MoveonlyType
&);
378 const boost::variant
<int, std::string
> foo1() { return ""; }
379 boost::variant
<int, std::string
> foo2() { return ""; }
381 inline void get_rvref_test()
383 boost::get
<std::string
>(foo1());
384 boost::get
<std::string
>(foo2());
386 boost::variant
<MoveonlyType
, int> v
;
389 boost::get
<MoveonlyType
>(boost::move(v
));
394 boost::get
<MoveonlyType
>(v
);
396 boost::relaxed_get
<MoveonlyType
&>(boost::variant
<MoveonlyType
, int>());
399 MoveonlyType
moved_from_variant(boost::get
<MoveonlyType
>(boost::move(v
)));
401 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
406 get_test_no_fallback();
409 get_recursive_test();
410 check_that_does_not_exist();
412 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
416 return boost::report_errors();