]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/variant/test/rvalue_test.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / variant / test / rvalue_test.cpp
CommitLineData
7c673cae
FG
1//-----------------------------------------------------------------------------
2// boost-libs variant/test/rvalue_test.cpp source file
3// See http://www.boost.org for updates, documentation, and revision history.
4//-----------------------------------------------------------------------------
5//
92f5a8d4 6// Copyright (c) 2012-2019 Antony Polukhin
7c673cae
FG
7//
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)
11
12#include "boost/config.hpp"
13
92f5a8d4 14#include "boost/core/lightweight_test.hpp"
7c673cae
FG
15#include "boost/variant.hpp"
16#include "boost/type_traits/is_nothrow_move_assignable.hpp"
17#include "boost/mpl/bool.hpp"
18
19#include <boost/blank.hpp>
20#include <boost/swap.hpp>
21
22namespace swap_ambiguouty_test_ns {
23 struct A {};
24 struct B {};
25
26 void swap_ambiguouty_test() {
27 // If boost::blank is not used, then it compiles.
28 typedef boost::variant<boost::blank, A, B> Variant;
29 Variant v1, v2;
30 swap(v1, v2);
31 }
32} // namespace swap_ambiguouty_test_ns
33
34// Most part of tests from this file require rvalue references support
35
36class move_copy_conting_class {
37public:
38 static unsigned int moves_count;
39 static unsigned int copy_count;
40
41 move_copy_conting_class(){}
42 move_copy_conting_class(BOOST_RV_REF(move_copy_conting_class) ) {
43 ++ moves_count;
44 }
45
46 move_copy_conting_class& operator=(BOOST_RV_REF(move_copy_conting_class) ) {
47 ++ moves_count;
48 return *this;
49 }
50
51 move_copy_conting_class(const move_copy_conting_class&) {
52 ++ copy_count;
53 }
54 move_copy_conting_class& operator=(BOOST_COPY_ASSIGN_REF(move_copy_conting_class) ) {
55 ++ copy_count;
56 return *this;
57 }
58};
59
60unsigned int move_copy_conting_class::moves_count = 0;
61unsigned int move_copy_conting_class::copy_count = 0;
62
63#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
64
65void run()
66{
67 // Making sure that internals of Boost.Move do not interfere with
68 // internals of Boost.Variant and in case of C++03 or C++98 compilation
69 // is still possible.
70 typedef boost::variant<int, move_copy_conting_class> variant_I_type;
71 variant_I_type v1, v2;
72 v1 = move_copy_conting_class();
73 v2 = v1;
74 v2 = boost::move(v1);
75 v1.swap(v2);
76
77 move_copy_conting_class val;
78 v2 = boost::move(val);
79 v2 = 10;
80
81 variant_I_type v3(boost::move(val));
82 variant_I_type v4(boost::move(v1));
83}
84
85void run1()
86{
92f5a8d4 87 BOOST_TEST(true);
7c673cae
FG
88}
89
90void run_move_only()
91{
92f5a8d4 92 BOOST_TEST(true);
7c673cae
FG
93}
94
95void run_moves_are_noexcept()
96{
92f5a8d4 97 BOOST_TEST(true);
7c673cae
FG
98}
99
100
101void run_const_rvalues()
102{
92f5a8d4 103 BOOST_TEST(true);
7c673cae
FG
104}
105
106
107#else
108
109
110void run()
111{
112 typedef boost::variant<int, move_copy_conting_class> variant_I_type;
113 variant_I_type v1, v2;
114
115 // Assuring that `move_copy_conting_class` was not created
92f5a8d4
TL
116 BOOST_TEST(move_copy_conting_class::copy_count == 0);
117 BOOST_TEST(move_copy_conting_class::moves_count == 0);
7c673cae
FG
118
119 v1 = move_copy_conting_class();
120 // Assuring that `move_copy_conting_class` was moved at least once
92f5a8d4 121 BOOST_TEST(move_copy_conting_class::moves_count != 0);
7c673cae
FG
122
123 unsigned int total_count = move_copy_conting_class::moves_count + move_copy_conting_class::copy_count;
124 move_copy_conting_class var;
125 v1 = 0;
126 move_copy_conting_class::moves_count = 0;
127 move_copy_conting_class::copy_count = 0;
128 v1 = var;
129 // Assuring that move assignment operator moves/copyes value not more times than copy assignment operator
92f5a8d4 130 BOOST_TEST(total_count <= move_copy_conting_class::moves_count + move_copy_conting_class::copy_count);
7c673cae
FG
131
132 move_copy_conting_class::moves_count = 0;
133 move_copy_conting_class::copy_count = 0;
134 v2 = boost::move(v1);
135 // Assuring that `move_copy_conting_class` in v1 was moved at least once and was not copied
92f5a8d4
TL
136 BOOST_TEST(move_copy_conting_class::moves_count != 0);
137 BOOST_TEST(move_copy_conting_class::copy_count == 0);
7c673cae
FG
138
139 v1 = move_copy_conting_class();
140 move_copy_conting_class::moves_count = 0;
141 move_copy_conting_class::copy_count = 0;
142 v2 = boost::move(v1);
143 // Assuring that `move_copy_conting_class` in v1 was moved at least once and was not copied
92f5a8d4
TL
144 BOOST_TEST(move_copy_conting_class::moves_count != 0);
145 BOOST_TEST(move_copy_conting_class::copy_count == 0);
7c673cae
FG
146 total_count = move_copy_conting_class::moves_count + move_copy_conting_class::copy_count;
147 move_copy_conting_class::moves_count = 0;
148 move_copy_conting_class::copy_count = 0;
149 v1 = v2;
150 // Assuring that move assignment operator moves/copyes value not more times than copy assignment operator
92f5a8d4 151 BOOST_TEST(total_count <= move_copy_conting_class::moves_count + move_copy_conting_class::copy_count);
7c673cae
FG
152
153
154 typedef boost::variant<move_copy_conting_class, int> variant_II_type;
155 variant_II_type v3;
156 move_copy_conting_class::moves_count = 0;
157 move_copy_conting_class::copy_count = 0;
158 v1 = boost::move(v3);
159 // Assuring that `move_copy_conting_class` in v3 was moved at least once (v1 and v3 have different types)
92f5a8d4 160 BOOST_TEST(move_copy_conting_class::moves_count != 0);
7c673cae
FG
161
162 move_copy_conting_class::moves_count = 0;
163 move_copy_conting_class::copy_count = 0;
164 v2 = boost::move(v1);
165 // Assuring that `move_copy_conting_class` in v1 was moved at least once (v1 and v3 have different types)
92f5a8d4 166 BOOST_TEST(move_copy_conting_class::moves_count != 0);
7c673cae
FG
167
168 move_copy_conting_class::moves_count = 0;
169 move_copy_conting_class::copy_count = 0;
170 variant_I_type v5(boost::move(v1));
171 // Assuring that `move_copy_conting_class` in v1 was moved at least once and was not copied
92f5a8d4
TL
172 BOOST_TEST(move_copy_conting_class::moves_count != 0);
173 BOOST_TEST(move_copy_conting_class::copy_count == 0);
7c673cae
FG
174
175 total_count = move_copy_conting_class::moves_count + move_copy_conting_class::copy_count;
176 move_copy_conting_class::moves_count = 0;
177 move_copy_conting_class::copy_count = 0;
178 variant_I_type v6(v1);
179 // Assuring that move constructor moves/copyes value not more times than copy constructor
92f5a8d4 180 BOOST_TEST(total_count <= move_copy_conting_class::moves_count + move_copy_conting_class::copy_count);
7c673cae
FG
181}
182
183void run1()
184{
185 move_copy_conting_class::moves_count = 0;
186 move_copy_conting_class::copy_count = 0;
187
188 move_copy_conting_class c1;
189 typedef boost::variant<int, move_copy_conting_class> variant_I_type;
190 variant_I_type v1(boost::move(c1));
191
192 // Assuring that `move_copy_conting_class` was not copyied
92f5a8d4
TL
193 BOOST_TEST(move_copy_conting_class::copy_count == 0);
194 BOOST_TEST(move_copy_conting_class::moves_count > 0);
7c673cae
FG
195}
196
197struct move_only_structure {
198 move_only_structure(){}
199 move_only_structure(move_only_structure&&){}
200 move_only_structure& operator=(move_only_structure&&) { return *this; }
201
202private:
203 move_only_structure(const move_only_structure&);
204 move_only_structure& operator=(const move_only_structure&);
205};
206
207struct visitor_returning_move_only_type: boost::static_visitor<move_only_structure> {
208 template <class T>
209 move_only_structure operator()(const T&) const {
210 return move_only_structure();
211 }
212};
213
214void run_move_only()
215{
216 move_only_structure mo;
217 boost::variant<int, move_only_structure > vi, vi2(static_cast<move_only_structure&&>(mo));
92f5a8d4
TL
218 BOOST_TEST(vi.which() == 0);
219 BOOST_TEST(vi2.which() == 1);
7c673cae
FG
220
221 vi = 10;
222 vi2 = 10;
92f5a8d4
TL
223 BOOST_TEST(vi.which() == 0);
224 BOOST_TEST(vi2.which() == 0);
7c673cae
FG
225
226 vi = static_cast<move_only_structure&&>(mo);
227 vi2 = static_cast<move_only_structure&&>(mo);
92f5a8d4 228 BOOST_TEST(vi.which() == 1);
7c673cae
FG
229
230 boost::variant<move_only_structure, int > rvi (1);
92f5a8d4 231 BOOST_TEST(rvi.which() == 1);
7c673cae 232 rvi = static_cast<move_only_structure&&>(mo);
92f5a8d4 233 BOOST_TEST(rvi.which() == 0);
7c673cae 234 rvi = 1;
92f5a8d4 235 BOOST_TEST(rvi.which() == 1);
7c673cae 236 rvi = static_cast<boost::variant<int, move_only_structure >&&>(vi2);
92f5a8d4 237 BOOST_TEST(rvi.which() == 0);
7c673cae
FG
238
239 move_only_structure from_visitor = boost::apply_visitor(visitor_returning_move_only_type(), vi);
240 (void)from_visitor;
241}
242
243void run_moves_are_noexcept() {
244#if !defined(BOOST_NO_CXX11_NOEXCEPT) && (!defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4 || __GNUC_MINOR__ >= 8)
245 typedef boost::variant<int, short, double> variant_noexcept_t;
92f5a8d4
TL
246 BOOST_TEST(boost::is_nothrow_move_assignable<variant_noexcept_t>::value);
247 BOOST_TEST(boost::is_nothrow_move_constructible<variant_noexcept_t>::value);
7c673cae
FG
248
249 typedef boost::variant<int, short, double, move_only_structure> variant_except_t;
92f5a8d4
TL
250 BOOST_TEST(!boost::is_nothrow_move_assignable<variant_except_t>::value);
251 BOOST_TEST(!boost::is_nothrow_move_constructible<variant_except_t>::value);
7c673cae
FG
252#endif
253}
254
255inline const std::string get_string() { return "test"; }
256inline const boost::variant<int, std::string> get_variant() { return std::string("test"); }
257inline const boost::variant<std::string, int> get_variant2() { return std::string("test"); }
258
259void run_const_rvalues()
260{
261 typedef boost::variant<int, std::string> variant_t;
262 const variant_t v1(get_string());
263 const variant_t v2(get_variant());
264 const variant_t v3(get_variant2());
265
266 variant_t v4, v5, v6, v7;
267 v4 = get_string();
268 v5 = get_variant();
269 v6 = get_variant2();
270 v7 = boost::move(v1);
271}
272
273#endif
274
275struct nothrow_copyable_throw_movable {
276 nothrow_copyable_throw_movable(){}
277 nothrow_copyable_throw_movable(const nothrow_copyable_throw_movable&) BOOST_NOEXCEPT {}
278 nothrow_copyable_throw_movable& operator=(const nothrow_copyable_throw_movable&) BOOST_NOEXCEPT { return *this; }
279#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
280 nothrow_copyable_throw_movable(nothrow_copyable_throw_movable&&) BOOST_NOEXCEPT_IF(false) {}
281 nothrow_copyable_throw_movable& operator=(nothrow_copyable_throw_movable&&) BOOST_NOEXCEPT_IF(false) { return *this; }
282#endif
283};
284
285// This test is created to cover the following situation:
286// https://svn.boost.org/trac/boost/ticket/8772
287void run_tricky_compilation_test()
288{
289 boost::variant<int, nothrow_copyable_throw_movable> v;
290 v = nothrow_copyable_throw_movable();
291}
292
293template <typename T>
294struct is_container : boost::mpl::false_ {};
295
296template <typename T>
297struct is_container<boost::variant<T> > : is_container<T> {};
298
299template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
300struct is_container<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
301 : boost::mpl::bool_<is_container<T0>::value
302 || is_container<boost::variant<BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)> >::value>
303{};
304
305void run_is_container_compilation_test()
306{
92f5a8d4
TL
307 BOOST_TEST((!is_container<boost::variant<double, int> >::value));
308 BOOST_TEST((!is_container<boost::variant<double, int, char> >::value));
309 BOOST_TEST((!is_container<boost::variant<double, int, char, float> >::value));
7c673cae
FG
310}
311
92f5a8d4 312int main()
7c673cae
FG
313{
314 swap_ambiguouty_test_ns::swap_ambiguouty_test();
315 run();
316 run1();
317 run_move_only();
318 run_moves_are_noexcept();
319 run_tricky_compilation_test();
320 run_const_rvalues();
321 run_is_container_compilation_test();
322
323#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ > 6)
324# ifdef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
92f5a8d4 325 BOOST_TEST(false &&
7c673cae
FG
326 "Something wrong with macro definitions. GCC-4.7+ is known to work with variadic templates"
327 );
328# endif
329#endif
330
92f5a8d4 331 return boost::report_errors();
7c673cae 332}