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-2017 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
16 #include "boost/variant/get.hpp"
17 #include "boost/variant/variant.hpp"
18 #include "boost/variant/polymorphic_get.hpp"
19 #include "boost/variant/recursive_wrapper.hpp"
20 #include "boost/test/minimal.hpp"
25 base() : trash(123) {}
26 base(const base
& b
) : trash(b
.trash
) { int i
= 100; (void)i
; }
27 const base
& operator=(const base
& b
) {
37 struct derived1
: base
{};
38 struct derived2
: base
{};
40 struct vbase
{ short trash
; virtual ~vbase(){} virtual int foo() const { return 0; } };
41 struct vderived1
: virtual vbase
{ virtual int foo() const { return 1; } };
42 struct vderived2
: virtual vbase
{ virtual int foo() const { return 3; } };
43 struct vderived3
: vderived1
, vderived2
{ virtual int foo() const { return 3; } };
45 typedef boost::variant
<int, base
, derived1
, derived2
, std::string
> var_t
;
46 typedef boost::variant
<int, derived1
, derived2
, std::string
> var_t_shortened
;
47 typedef boost::variant
<base
, derived1
, derived2
> var_t_no_fallback
;
48 typedef boost::variant
<int&, base
&, derived1
&, derived2
&, std::string
&> var_ref_t
;
49 typedef boost::variant
<const int&, const base
&, const derived1
&, const derived2
&, const std::string
&> var_cref_t
;
51 struct recursive_structure
;
52 typedef boost::variant
<
53 int, base
, derived1
, derived2
, std::string
, boost::recursive_wrapper
<recursive_structure
>
55 struct recursive_structure
{ var_req_t var
; };
57 template <class TypeInVariant
, class V
, class TestType
>
58 inline void check_polymorphic_get_on_types_impl_single_type(V
* v
)
60 typedef typename
boost::add_reference
<TestType
>::type ref_test_t
;
61 typedef typename
boost::add_reference
<const TestType
>::type cref_test_t
;
62 const bool exact_same
= !!boost::is_same
<TypeInVariant
, TestType
>::value
;
63 const bool ref_same
= !!boost::is_same
<TypeInVariant
, ref_test_t
>::value
;
65 if (exact_same
|| ref_same
) {
66 BOOST_CHECK(boost::polymorphic_get
<TestType
>(v
));
67 BOOST_CHECK(boost::polymorphic_get
<const TestType
>(v
));
68 BOOST_CHECK(boost::polymorphic_strict_get
<TestType
>(v
));
69 BOOST_CHECK(boost::polymorphic_strict_get
<const TestType
>(v
));
70 BOOST_CHECK(boost::polymorphic_relaxed_get
<TestType
>(v
));
71 BOOST_CHECK(boost::polymorphic_relaxed_get
<const TestType
>(v
));
73 BOOST_CHECK(boost::polymorphic_get
<cref_test_t
>(v
));
74 BOOST_CHECK(boost::polymorphic_strict_get
<cref_test_t
>(v
));
75 BOOST_CHECK(boost::polymorphic_relaxed_get
<cref_test_t
>(v
));
78 BOOST_CHECK(boost::polymorphic_get
<ref_test_t
>(v
));
79 BOOST_CHECK(boost::polymorphic_get
<cref_test_t
>(v
));
80 BOOST_CHECK(boost::polymorphic_strict_get
<ref_test_t
>(v
));
81 BOOST_CHECK(boost::polymorphic_strict_get
<cref_test_t
>(v
));
82 BOOST_CHECK(boost::polymorphic_relaxed_get
<ref_test_t
>(v
));
83 BOOST_CHECK(boost::polymorphic_relaxed_get
<cref_test_t
>(v
));
86 BOOST_CHECK(!boost::polymorphic_get
<TestType
>(v
));
87 BOOST_CHECK(!boost::polymorphic_get
<const TestType
>(v
));
88 BOOST_CHECK(!boost::polymorphic_strict_get
<TestType
>(v
));
89 BOOST_CHECK(!boost::polymorphic_strict_get
<const TestType
>(v
));
90 BOOST_CHECK(!boost::polymorphic_relaxed_get
<TestType
>(v
));
91 BOOST_CHECK(!boost::polymorphic_relaxed_get
<const TestType
>(v
));
95 template <class T
, class V
, class TestType
>
96 inline void check_get_on_types_impl_single_type(V
* v
)
98 typedef typename
boost::add_reference
<TestType
>::type ref_test_t
;
99 typedef typename
boost::add_reference
<const TestType
>::type cref_test_t
;
100 const bool exact_same
= !!boost::is_same
<T
, TestType
>::value
;
101 const bool ref_same
= !!boost::is_same
<T
, ref_test_t
>::value
;
103 if (exact_same
|| ref_same
) {
104 BOOST_CHECK(boost::get
<TestType
>(v
));
105 BOOST_CHECK(boost::get
<const TestType
>(v
));
106 BOOST_CHECK(boost::strict_get
<TestType
>(v
));
107 BOOST_CHECK(boost::strict_get
<const TestType
>(v
));
108 BOOST_CHECK(boost::relaxed_get
<TestType
>(v
));
109 BOOST_CHECK(boost::relaxed_get
<const TestType
>(v
));
111 BOOST_CHECK(boost::get
<cref_test_t
>(v
));
112 BOOST_CHECK(boost::strict_get
<cref_test_t
>(v
));
113 BOOST_CHECK(boost::relaxed_get
<cref_test_t
>(v
));
116 BOOST_CHECK(boost::get
<ref_test_t
>(v
));
117 BOOST_CHECK(boost::get
<cref_test_t
>(v
));
118 BOOST_CHECK(boost::strict_get
<ref_test_t
>(v
));
119 BOOST_CHECK(boost::strict_get
<cref_test_t
>(v
));
120 BOOST_CHECK(boost::relaxed_get
<ref_test_t
>(v
));
121 BOOST_CHECK(boost::relaxed_get
<cref_test_t
>(v
));
124 BOOST_CHECK(!boost::get
<TestType
>(v
));
125 BOOST_CHECK(!boost::get
<const TestType
>(v
));
126 BOOST_CHECK(!boost::strict_get
<TestType
>(v
));
127 BOOST_CHECK(!boost::strict_get
<const TestType
>(v
));
128 BOOST_CHECK(!boost::relaxed_get
<TestType
>(v
));
129 BOOST_CHECK(!boost::relaxed_get
<const TestType
>(v
));
133 template <class T
, class V
>
134 inline void check_get_on_types_impl(V
* v
)
136 check_get_on_types_impl_single_type
<T
, V
, int>(v
);
137 check_polymorphic_get_on_types_impl_single_type
<T
, V
, int>(v
);
139 check_get_on_types_impl_single_type
<T
, V
, base
>(v
);
141 check_get_on_types_impl_single_type
<T
, V
, derived1
>(v
);
142 check_polymorphic_get_on_types_impl_single_type
<T
, V
, derived1
>(v
);
144 check_get_on_types_impl_single_type
<T
, V
, derived2
>(v
);
145 check_polymorphic_get_on_types_impl_single_type
<T
, V
, derived2
>(v
);
147 check_get_on_types_impl_single_type
<T
, V
, std::string
>(v
);
148 check_polymorphic_get_on_types_impl_single_type
<T
, V
, std::string
>(v
);
150 // Never exist in here
151 BOOST_CHECK(!boost::relaxed_get
<short>(v
));
152 BOOST_CHECK(!boost::relaxed_get
<const short>(v
));
153 BOOST_CHECK(!boost::relaxed_get
<char>(v
));
154 BOOST_CHECK(!boost::relaxed_get
<char*>(v
));
155 BOOST_CHECK(!boost::relaxed_get
<bool>(v
));
156 BOOST_CHECK(!boost::relaxed_get
<const bool>(v
));
158 BOOST_CHECK(!boost::polymorphic_relaxed_get
<short>(v
));
159 BOOST_CHECK(!boost::polymorphic_relaxed_get
<const short>(v
));
160 BOOST_CHECK(!boost::polymorphic_relaxed_get
<char>(v
));
161 BOOST_CHECK(!boost::polymorphic_relaxed_get
<char*>(v
));
162 BOOST_CHECK(!boost::polymorphic_relaxed_get
<bool>(v
));
163 BOOST_CHECK(!boost::polymorphic_relaxed_get
<const bool>(v
));
165 boost::get
<T
>(*v
); // Must compile
166 boost::get
<const T
>(*v
); // Must compile
167 boost::strict_get
<T
>(*v
); // Must compile
168 boost::strict_get
<const T
>(*v
); // Must compile
170 bool is_ref
= boost::is_lvalue_reference
<T
>::value
;
173 boost::polymorphic_get
<T
>(*v
); // Must compile
174 boost::polymorphic_get
<const T
>(*v
); // Must compile
175 boost::polymorphic_strict_get
<T
>(*v
); // Must compile
176 boost::polymorphic_strict_get
<const T
>(*v
); // Must compile
180 template <class T
, class V
>
181 inline void check_get_on_types(V
* v
)
183 check_get_on_types_impl
<T
, V
>(v
);
184 check_get_on_types_impl
<T
, const V
>(v
);
187 inline void get_test()
190 check_get_on_types
<int>(&v
);
192 var_t(base()).swap(v
);
193 check_get_on_types
<base
>(&v
);
195 var_t(derived1()).swap(v
);
196 check_get_on_types
<derived1
>(&v
);
198 var_t(derived2()).swap(v
);
199 check_get_on_types
<derived2
>(&v
);
201 var_t(std::string("Hello")).swap(v
);
202 check_get_on_types
<std::string
>(&v
);
204 var_t_shortened vs
= derived2();
205 check_polymorphic_get_on_types_impl_single_type
<derived2
, var_t_shortened
, int>(&vs
);
206 check_polymorphic_get_on_types_impl_single_type
<derived2
, const var_t_shortened
, int>(&vs
);
207 // Checking that Base is really determinated
208 check_polymorphic_get_on_types_impl_single_type
<base
, var_t_shortened
, base
>(&vs
);
209 check_polymorphic_get_on_types_impl_single_type
<base
, const var_t_shortened
, base
>(&vs
);
212 check_polymorphic_get_on_types_impl_single_type
<derived2
, var_t_shortened
, int>(&vs
);
213 check_polymorphic_get_on_types_impl_single_type
<derived2
, const var_t_shortened
, int>(&vs
);
214 // Checking that Base is really determinated
215 check_polymorphic_get_on_types_impl_single_type
<base
, var_t_shortened
, base
>(&vs
);
216 check_polymorphic_get_on_types_impl_single_type
<base
, const var_t_shortened
, base
>(&vs
);
219 inline void get_test_no_fallback()
222 var_t_no_fallback(base()).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
<base
, var_t_no_fallback
, base
>(&v
);
226 check_get_on_types_impl_single_type
<base
, const var_t_no_fallback
, base
>(&v
);
228 var_t_no_fallback(derived1()).swap(v
);
229 check_polymorphic_get_on_types_impl_single_type
<base
, var_t_no_fallback
, base
>(&v
);
230 check_polymorphic_get_on_types_impl_single_type
<base
, const var_t_no_fallback
, base
>(&v
);
231 check_get_on_types_impl_single_type
<derived1
, var_t_no_fallback
, derived1
>(&v
);
232 check_get_on_types_impl_single_type
<derived1
, const var_t_no_fallback
, derived1
>(&v
);
234 var_t_no_fallback(derived2()).swap(v
);
235 check_polymorphic_get_on_types_impl_single_type
<base
, var_t_no_fallback
, base
>(&v
);
236 check_polymorphic_get_on_types_impl_single_type
<base
, const var_t_no_fallback
, base
>(&v
);
237 check_get_on_types_impl_single_type
<derived2
, var_t_no_fallback
, derived2
>(&v
);
238 check_get_on_types_impl_single_type
<derived2
, const var_t_no_fallback
, derived2
>(&v
);
241 inline void get_ref_test()
245 check_get_on_types
<int>(&v
);
246 check_get_on_types
<int&>(&v
);
250 check_get_on_types
<base
>(&v1
);
251 check_get_on_types
<base
&>(&v1
);
255 check_get_on_types
<derived1
>(&v2
);
256 check_get_on_types
<derived1
&>(&v2
);
260 check_get_on_types
<derived2
>(&v3
);
261 check_get_on_types
<derived2
&>(&v3
);
263 std::string
s("Hello");
265 check_get_on_types
<std::string
>(&v4
);
266 check_get_on_types
<std::string
&>(&v4
);
270 inline void get_cref_test()
274 BOOST_CHECK(boost::get
<const int>(&v
));
275 BOOST_CHECK(boost::get
<const int&>(&v
));
276 BOOST_CHECK(!boost::get
<const base
>(&v
));
280 BOOST_CHECK(boost::get
<const base
>(&v1
));
281 BOOST_CHECK(!boost::get
<const derived1
>(&v1
));
282 BOOST_CHECK(!boost::get
<const int>(&v1
));
284 std::string
s("Hello");
285 const var_cref_t v4
= s
;
286 BOOST_CHECK(boost::get
<const std::string
>(&v4
));
287 BOOST_CHECK(!boost::get
<const int>(&v4
));
290 inline void get_recursive_test()
293 check_get_on_types
<int>(&v
);
295 var_req_t(base()).swap(v
);
296 check_get_on_types
<base
>(&v
);
298 var_req_t(derived1()).swap(v
);
299 check_get_on_types
<derived1
>(&v
);
301 var_req_t(derived2()).swap(v
);
302 check_get_on_types
<derived2
>(&v
);
304 var_req_t(std::string("Hello")).swap(v
);
305 check_get_on_types
<std::string
>(&v
);
307 recursive_structure s
= { v
}; // copying "v"
309 check_get_on_types
<recursive_structure
>(&v
);
313 inline void check_that_does_not_exist_impl()
315 using namespace boost::detail::variant
;
317 BOOST_CHECK((holds_element
<T
, const int>::value
));
318 BOOST_CHECK((!holds_element
<T
, short>::value
));
319 BOOST_CHECK((!holds_element
<T
, short>::value
));
320 BOOST_CHECK((!holds_element
<T
, const short>::value
));
321 BOOST_CHECK((!holds_element
<T
, char*>::value
));
322 BOOST_CHECK((!holds_element
<T
, const char*>::value
));
323 BOOST_CHECK((!holds_element
<T
, char[5]>::value
));
324 BOOST_CHECK((!holds_element
<T
, const char[5]>::value
));
325 BOOST_CHECK((!holds_element
<T
, bool>::value
));
326 BOOST_CHECK((!holds_element
<T
, const bool>::value
));
328 BOOST_CHECK((!holds_element
<T
, boost::recursive_wrapper
<int> >::value
));
329 BOOST_CHECK((!holds_element
<T
, boost::recursive_wrapper
<short> >::value
));
330 BOOST_CHECK((!holds_element
<T
, boost::detail::reference_content
<short> >::value
));
333 BOOST_CHECK((holds_element_polymorphic
<T
, const int>::value
));
334 BOOST_CHECK((!holds_element_polymorphic
<T
, short>::value
));
335 BOOST_CHECK((!holds_element_polymorphic
<T
, short>::value
));
336 BOOST_CHECK((!holds_element_polymorphic
<T
, const short>::value
));
337 BOOST_CHECK((!holds_element_polymorphic
<T
, char*>::value
));
338 BOOST_CHECK((!holds_element_polymorphic
<T
, const char*>::value
));
339 BOOST_CHECK((!holds_element_polymorphic
<T
, char[5]>::value
));
340 BOOST_CHECK((!holds_element_polymorphic
<T
, const char[5]>::value
));
341 BOOST_CHECK((!holds_element_polymorphic
<T
, bool>::value
));
342 BOOST_CHECK((!holds_element_polymorphic
<T
, const bool>::value
));
344 BOOST_CHECK((!holds_element_polymorphic
<T
, boost::recursive_wrapper
<int> >::value
));
345 BOOST_CHECK((!holds_element_polymorphic
<T
, boost::recursive_wrapper
<short> >::value
));
346 BOOST_CHECK((!holds_element_polymorphic
<T
, boost::detail::reference_content
<short> >::value
));
349 inline void check_that_does_not_exist()
351 using namespace boost::detail::variant
;
353 BOOST_CHECK((holds_element
<var_t
, int>::value
));
354 BOOST_CHECK((holds_element
<var_ref_t
, int>::value
));
355 BOOST_CHECK((!holds_element
<var_cref_t
, int>::value
));
357 check_that_does_not_exist_impl
<var_t
>();
358 check_that_does_not_exist_impl
<var_ref_t
>();
359 check_that_does_not_exist_impl
<var_cref_t
>();
360 check_that_does_not_exist_impl
<var_req_t
>();
363 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
369 MoveonlyType(MoveonlyType
&&) {}
370 void operator=(MoveonlyType
&&) {}
373 MoveonlyType(const MoveonlyType
&);
374 void operator=(const MoveonlyType
&);
377 const boost::variant
<int, std::string
> foo1() { return ""; }
378 boost::variant
<int, std::string
> foo2() { return ""; }
380 inline void get_rvref_test()
382 boost::get
<std::string
>(foo1());
383 boost::get
<std::string
>(foo2());
385 boost::variant
<MoveonlyType
, int> v
;
388 boost::get
<MoveonlyType
>(boost::move(v
));
393 boost::get
<MoveonlyType
>(v
);
395 boost::relaxed_get
<MoveonlyType
&>(boost::variant
<MoveonlyType
, int>());
398 MoveonlyType
moved_from_variant(boost::get
<MoveonlyType
>(boost::move(v
)));
400 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
402 int test_main(int , char* [])
405 get_test_no_fallback();
408 get_recursive_test();
409 check_that_does_not_exist();
411 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
415 return boost::exit_success
;