1// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
2//
3// Distributed under the Boost Software License, Version 1.0. (See
4// accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt)
6
7// For more information, see http://www.boost.org
8
9// tuple_test_bench.cpp --------------------------------
10
11#include "boost/tuple/tuple.hpp"
12#include "boost/tuple/tuple_comparison.hpp"
13
14#include "boost/type_traits/is_const.hpp"
15#include "boost/ref.hpp"
16#include "boost/core/lightweight_test.hpp"
17
18#include <string>
19#include <utility>
20
21#define BOOST_CHECK BOOST_TEST
22
23using namespace boost;
24
25// ----------------------------------------------------------------------------
26// helpers
27// ----------------------------------------------------------------------------
28
29class A {};
30class B {};
31class C {};
32
33// classes with different kinds of conversions
34class AA {};
35class BB : public AA {};
36struct CC { CC() {} CC(const BB&) {} };
37struct DD { operator CC() const { return CC(); }; };
38
39// something to prevent warnings for unused variables
40template<class T> void dummy(const T&) {}
41
42// no public default constructor
43class foo {
44public:
45 explicit foo(int v) : val(v) {}
46
47 bool operator==(const foo& other) const {
48 return val == other.val;
49 }
50
51private:
52 foo() {}
53 int val;
54};
55
56// another class without a public default constructor
57class no_def_constructor {
58 no_def_constructor() {}
59public:
60 no_def_constructor(std::string) {}
61};
62
63// A non-copyable class
64class no_copy {
65 no_copy(const no_copy&) {}
66public:
67 no_copy() {};
68};
69
70
71// ----------------------------------------------------------------------------
72// Testing different element types --------------------------------------------
73// ----------------------------------------------------------------------------
74
75
76typedef tuple<int> t1;
77
78typedef tuple<double&, const double&, const double, double*, const double*> t2;
79typedef tuple<A, int(*)(char, int), C> t3;
80typedef tuple<std::string, std::pair<A, B> > t4;
81typedef tuple<A*, tuple<const A*, const B&, C>, bool, void*> t5;
82typedef tuple<volatile int, const volatile char&, int(&)(float) > t6;
83
84# if !defined(BOOST_BORLANDC) || BOOST_BORLANDC > 0x0551
85typedef tuple<B(A::*)(C&), A&> t7;
86#endif
87
88// -----------------------------------------------------------------------
89// -tuple construction tests ---------------------------------------------
90// -----------------------------------------------------------------------
91
92
93no_copy y;
94tuple<no_copy&> x = tuple<no_copy&>(y); // ok
95
96char cs[10];
97tuple<char(&)[10]> v2(cs); // ok
98
99void
100construction_test()
101{
102
103 // Note, the get function can be called without the tuples:: qualifier,
104 // as it is lifted to namespace boost with a "using tuples::get" but
105 // MSVC 6.0 just cannot find get without the namespace qualifier
106
107 tuple<int> t1;
108 BOOST_CHECK(get<0>(t1) == int());
109
110 tuple<float> t2(5.5f);
111 BOOST_CHECK(get<0>(t2) > 5.4f && get<0>(t2) < 5.6f);
112
113 tuple<foo> t3(foo(12));
114 BOOST_CHECK(get<0>(t3) == foo(12));
115
116 tuple<double> t4(t2);
117 BOOST_CHECK(get<0>(t4) > 5.4 && get<0>(t4) < 5.6);
118
119 tuple<int, float> t5;
120 BOOST_CHECK(get<0>(t5) == int());
121 BOOST_CHECK(get<1>(t5) == float());
122
123 tuple<int, float> t6(12, 5.5f);
124 BOOST_CHECK(get<0>(t6) == 12);
125 BOOST_CHECK(get<1>(t6) > 5.4f && get<1>(t6) < 5.6f);
126
127 tuple<int, float> t7(t6);
128 BOOST_CHECK(get<0>(t7) == 12);
129 BOOST_CHECK(get<1>(t7) > 5.4f && get<1>(t7) < 5.6f);
130
131 tuple<long, double> t8(t6);
132 BOOST_CHECK(get<0>(t8) == 12);
133 BOOST_CHECK(get<1>(t8) > 5.4f && get<1>(t8) < 5.6f);
134
135 dummy(
136 tuple<no_def_constructor, no_def_constructor, no_def_constructor>(
137 std::string("Jaba"), // ok, since the default
138 std::string("Daba"), // constructor is not used
139 std::string("Doo")
140 )
141 );
142
143// testing default values
144 dummy(tuple<int, double>());
145 dummy(tuple<int, double>(1));
146 dummy(tuple<int, double>(1,3.14));
147
148
149 // dummy(tuple<double&>()); // should fail, not defaults for references
150 // dummy(tuple<const double&>()); // likewise
151
152 double dd = 5;
153 dummy(tuple<double&>(dd)); // ok
154
155 dummy(tuple<const double&>(dd+3.14)); // ok, but dangerous
156
157 // dummy(tuple<double&>(dd+3.14)); // should fail,
158 // // temporary to non-const reference
159}
160
161
162// ----------------------------------------------------------------------------
163// - testing element access ---------------------------------------------------
164// ----------------------------------------------------------------------------
165
166void element_access_test()
167{
168 double d = 2.7;
169 A a;
170 tuple<int, double&, const A&, int> t(1, d, a, 2);
171 const tuple<int, double&, const A, int> ct = t;
172
173 int i = get<0>(c&: t);
174 int i2 = get<3>(c&: t);
175
176 BOOST_CHECK(i == 1 && i2 == 2);
177
178 int j = get<0>(c: ct);
179 BOOST_CHECK(j == 1);
180
181 get<0>(c&: t) = 5;
182 BOOST_CHECK(t.head == 5);
183
184 // get<0>(ct) = 5; // can't assign to const
185
186 double e = get<1>(c&: t);
187 BOOST_CHECK(e > 2.69 && e < 2.71);
188
189 get<1>(c&: t) = 3.14+i;
190 BOOST_CHECK(get<1>(t) > 4.13 && get<1>(t) < 4.15);
191
192 // get<4>(t) = A(); // can't assign to const
193 // dummy(get<5>(ct)); // illegal index
194
195 ++get<0>(c&: t);
196 BOOST_CHECK(get<0>(t) == 6);
197
198 BOOST_STATIC_ASSERT((boost::is_const<boost::tuples::element<0, tuple<int, float> >::type>::value != true));
199#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
200 BOOST_STATIC_ASSERT((boost::is_const<boost::tuples::element<0, const tuple<int, float> >::type>::value));
201#endif
202
203 BOOST_STATIC_ASSERT((boost::is_const<boost::tuples::element<1, tuple<int, float> >::type>::value != true));
204#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
205 BOOST_STATIC_ASSERT((boost::is_const<boost::tuples::element<1, const tuple<int, float> >::type>::value));
206#endif
207
208
209 dummy(i); dummy(i2); dummy(j); dummy(e); // avoid warns for unused variables
210}
211
212
213// ----------------------------------------------------------------------------
214// - copying tuples -----------------------------------------------------------
215// ----------------------------------------------------------------------------
216
217
218
219void
220copy_test()
221{
222 tuple<int, char> t1(4, 'a');
223 tuple<int, char> t2(5, 'b');
224 t2 = t1;
225 BOOST_CHECK(get<0>(t1) == get<0>(t2));
226 BOOST_CHECK(get<1>(t1) == get<1>(t2));
227
228 tuple<long, std::string> t3(2, "a");
229 t3 = t1;
230 BOOST_CHECK((double)get<0>(t1) == get<0>(t3));
231 BOOST_CHECK(get<1>(t1) == get<1>(t3)[0]);
232
233// testing copy and assignment with implicit conversions between elements
234// testing tie
235
236 tuple<char, BB*, BB, DD> t;
237 tuple<int, AA*, CC, CC> a(t);
238 a = t;
239
240 int i; char c; double d;
241 tie(t0&: i, t1&: c, t2&: d) = make_tuple(t0: 1, t1: 'a', t2: 5.5);
242
243 BOOST_CHECK(i==1);
244 BOOST_CHECK(c=='a');
245 BOOST_CHECK(d>5.4 && d<5.6);
246}
247
248void
249mutate_test()
250{
251 tuple<int, float, bool, foo> t1(5, 12.2f, true, foo(4));
252 get<0>(c&: t1) = 6;
253 get<1>(c&: t1) = 2.2f;
254 get<2>(c&: t1) = false;
255 get<3>(c&: t1) = foo(5);
256
257 BOOST_CHECK(get<0>(t1) == 6);
258 BOOST_CHECK(get<1>(t1) > 2.1f && get<1>(t1) < 2.3f);
259 BOOST_CHECK(get<2>(t1) == false);
260 BOOST_CHECK(get<3>(t1) == foo(5));
261}
262
263// ----------------------------------------------------------------------------
264// make_tuple tests -----------------------------------------------------------
265// ----------------------------------------------------------------------------
266
267void
268make_tuple_test()
269{
270 tuple<int, char> t1 = make_tuple(t0: 5, t1: 'a');
271 BOOST_CHECK(get<0>(t1) == 5);
272 BOOST_CHECK(get<1>(t1) == 'a');
273
274 tuple<int, std::string> t2;
275 t2 = boost::make_tuple(t0: (short int)2, t1: std::string("Hi"));
276 BOOST_CHECK(get<0>(t2) == 2);
277 BOOST_CHECK(get<1>(t2) == "Hi");
278
279
280 A a = A(); B b;
281 const A ca = a;
282 make_tuple(t0: boost::cref(t: a), t1: b);
283 make_tuple(t0: boost::ref(t&: a), t1: b);
284 make_tuple(t0: boost::ref(t&: a), t1: boost::cref(t: b));
285
286 make_tuple(t0: boost::ref(t: ca));
287
288// the result of make_tuple is assignable:
289 BOOST_CHECK(make_tuple(2, 4, 6) ==
290 (make_tuple(1, 2, 3) = make_tuple(2, 4, 6)));
291
292#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
293 make_tuple(t0: "Donald", t1: "Daisy"); // should work;
294#endif
295 // std::make_pair("Doesn't","Work"); // fails
296
297// You can store a reference to a function in a tuple
298 tuple<void(&)()> adf(make_tuple_test);
299
300 dummy(adf); // avoid warning for unused variable
301
302// But make_tuple doesn't work
303// with function references, since it creates a const qualified function type
304
305// make_tuple(make_tuple_test);
306
307// With function pointers, make_tuple works just fine
308
309#if !defined(BOOST_BORLANDC) || BOOST_BORLANDC > 0x0551
310 make_tuple(t0: &make_tuple_test);
311#endif
312
313// NOTE:
314//
315// wrapping it the function reference with ref helps on gcc 2.95.2.
316// on edg 2.43. it results in a catastrophic error?
317
318// make_tuple(ref(foo3));
319
320// It seems that edg can't use implicitly the ref's conversion operator, e.g.:
321// typedef void (&func_t) (void);
322// func_t fref = static_cast<func_t>(ref(make_tuple_test)); // works fine
323// func_t fref = ref(make_tuple_test); // error
324
325// This is probably not a very common situation, so currently
326// I don't know how which compiler is right (JJ)
327}
328
329void
330tie_test()
331{
332 int a;
333 char b;
334 foo c(5);
335
336 tie(t0&: a, t1&: b, t2&: c) = make_tuple(t0: 2, t1: 'a', t2: foo(3));
337 BOOST_CHECK(a == 2);
338 BOOST_CHECK(b == 'a');
339 BOOST_CHECK(c == foo(3));
340
341 tie(t0&: a, t1&: tuples::ignore, t2&: c) = make_tuple(t0: (short int)5, t1: false, t2: foo(5));
342 BOOST_CHECK(a == 5);
343 BOOST_CHECK(b == 'a');
344 BOOST_CHECK(c == foo(5));
345
346// testing assignment from std::pair
347 int i, j;
348 tie (t0&: i, t1&: j) = std::make_pair(x: 1, y: 2);
349 BOOST_CHECK(i == 1 && j == 2);
350
351 tuple<int, int, float> ta;
352#ifdef E11
353 ta = std::make_pair(1, 2); // should fail, tuple is of length 3, not 2
354#endif
355
356 dummy(ta);
357}
358
359
360// ----------------------------------------------------------------------------
361// - testing tuple equality -------------------------------------------------
362// ----------------------------------------------------------------------------
363
364void
365equality_test()
366{
367 tuple<int, char> t1(5, 'a');
368 tuple<int, char> t2(5, 'a');
369 BOOST_CHECK(t1 == t2);
370
371 tuple<int, char> t3(5, 'b');
372 tuple<int, char> t4(2, 'a');
373 BOOST_CHECK(t1 != t3);
374 BOOST_CHECK(t1 != t4);
375 BOOST_CHECK(!(t1 != t2));
376}
377
378
379// ----------------------------------------------------------------------------
380// - testing tuple comparisons -----------------------------------------------
381// ----------------------------------------------------------------------------
382
383void
384ordering_test()
385{
386 tuple<int, float> t1(4, 3.3f);
387 tuple<short, float> t2(5, 3.3f);
388 tuple<long, double> t3(5, 4.4);
389 BOOST_CHECK(t1 < t2);
390 BOOST_CHECK(t1 <= t2);
391 BOOST_CHECK(t2 > t1);
392 BOOST_CHECK(t2 >= t1);
393 BOOST_CHECK(t2 < t3);
394 BOOST_CHECK(t2 <= t3);
395 BOOST_CHECK(t3 > t2);
396 BOOST_CHECK(t3 >= t2);
397
398}
399
400
401// ----------------------------------------------------------------------------
402// - testing cons lists -------------------------------------------------------
403// ----------------------------------------------------------------------------
404void cons_test()
405{
406 using tuples::cons;
407 using tuples::null_type;
408
409 cons<volatile float, null_type> a(1, null_type());
410 cons<const int, cons<volatile float, null_type> > b(2,a);
411 int i = 3;
412 cons<int&, cons<const int, cons<volatile float, null_type> > > c(i, b);
413 BOOST_CHECK(make_tuple(3,2,1)==c);
414
415 cons<char, cons<int, cons<float, null_type> > > x;
416 dummy(x);
417}
418
419// ----------------------------------------------------------------------------
420// - testing const tuples -----------------------------------------------------
421// ----------------------------------------------------------------------------
422void const_tuple_test()
423{
424 const tuple<int, float> t1(5, 3.25f);
425 BOOST_CHECK(get<0>(t1) == 5);
426 BOOST_CHECK(get<1>(t1) == 3.25f);
427}
428
429// ----------------------------------------------------------------------------
430// - testing length -----------------------------------------------------------
431// ----------------------------------------------------------------------------
432void tuple_length_test()
433{
434 typedef tuple<int, float, double> t1;
435 using tuples::cons;
436 typedef cons<int, cons< float, cons <double, tuples::null_type> > > t1_cons;
437 typedef tuple<> t2;
438 typedef tuples::null_type t3;
439
440 BOOST_STATIC_ASSERT(tuples::length<t1>::value == 3);
441 BOOST_STATIC_ASSERT(tuples::length<t1_cons>::value == 3);
442 BOOST_STATIC_ASSERT(tuples::length<t2>::value == 0);
443 BOOST_STATIC_ASSERT(tuples::length<t3>::value == 0);
444
445}
446
447// ----------------------------------------------------------------------------
448// - testing swap -----------------------------------------------------------
449// ----------------------------------------------------------------------------
450void tuple_swap_test()
451{
452 tuple<int, float, double> t1(1, 2.0f, 3.0), t2(4, 5.0f, 6.0);
453 swap(lhs&: t1, rhs&: t2);
454 BOOST_CHECK(get<0>(t1) == 4);
455 BOOST_CHECK(get<1>(t1) == 5.0f);
456 BOOST_CHECK(get<2>(t1) == 6.0);
457 BOOST_CHECK(get<0>(t2) == 1);
458 BOOST_CHECK(get<1>(t2) == 2.0f);
459 BOOST_CHECK(get<2>(t2) == 3.0);
460
461 int i = 1,j = 2;
462 boost::tuple<int&> t3(i), t4(j);
463 swap(lhs&: t3, rhs&: t4);
464 BOOST_CHECK(i == 2);
465 BOOST_CHECK(j == 1);
466}
467
468
469
470// ----------------------------------------------------------------------------
471// - main ---------------------------------------------------------------------
472// ----------------------------------------------------------------------------
473
474int main() {
475
476 construction_test();
477 element_access_test();
478 copy_test();
479 mutate_test();
480 make_tuple_test();
481 tie_test();
482 equality_test();
483 ordering_test();
484 cons_test();
485 const_tuple_test();
486 tuple_length_test();
487 tuple_swap_test();
488
489 return boost::report_errors();
490}
491

source code of boost/libs/tuple/test/tuple_test_bench.cpp