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
23 using namespace boost;
24
25 // ----------------------------------------------------------------------------
26 // helpers
27 // ----------------------------------------------------------------------------
28
29 class A {};
30 class B {};
31 class C {};
32
33 // classes with different kinds of conversions
34 class AA {};
35 class BB : public AA {};
CCCC36 struct CC { CC() {} CC(const BB&) {} };
operator CCDD37 struct DD { operator CC() const { return CC(); }; };
38
39 // something to prevent warnings for unused variables
dummy(const T &)40 template<class T> void dummy(const T&) {}
41
42 // no public default constructor
43 class foo {
44 public:
foo(int v)45 explicit foo(int v) : val(v) {}
46
operator ==(const foo & other) const47 bool operator==(const foo& other) const {
48 return val == other.val;
49 }
50
51 private:
foo()52 foo() {}
53 int val;
54 };
55
56 // another class without a public default constructor
57 class no_def_constructor {
no_def_constructor()58 no_def_constructor() {}
59 public:
no_def_constructor(std::string)60 no_def_constructor(std::string) {}
61 };
62
63 // A non-copyable class
64 class no_copy {
no_copy(const no_copy &)65 no_copy(const no_copy&) {}
66 public:
no_copy()67 no_copy() {};
68 };
69
70
71 // ----------------------------------------------------------------------------
72 // Testing different element types --------------------------------------------
73 // ----------------------------------------------------------------------------
74
75
76 typedef tuple<int> t1;
77
78 typedef tuple<double&, const double&, const double, double*, const double*> t2;
79 typedef tuple<A, int(*)(char, int), C> t3;
80 typedef tuple<std::string, std::pair<A, B> > t4;
81 typedef tuple<A*, tuple<const A*, const B&, C>, bool, void*> t5;
82 typedef tuple<volatile int, const volatile char&, int(&)(float) > t6;
83
84 # if !defined(BOOST_BORLANDC) || BOOST_BORLANDC > 0x0551
85 typedef tuple<B(A::*)(C&), A&> t7;
86 #endif
87
88 // -----------------------------------------------------------------------
89 // -tuple construction tests ---------------------------------------------
90 // -----------------------------------------------------------------------
91
92
93 no_copy y;
94 tuple<no_copy&> x = tuple<no_copy&>(y); // ok
95
96 char cs[10];
97 tuple<char(&)[10]> v2(cs); // ok
98
99 void
construction_test()100 construction_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
element_access_test()166 void 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>(t);
174 int i2 = get<3>(t);
175
176 BOOST_CHECK(i == 1 && i2 == 2);
177
178 int j = get<0>(ct);
179 BOOST_CHECK(j == 1);
180
181 get<0>(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>(t);
187 BOOST_CHECK(e > 2.69 && e < 2.71);
188
189 get<1>(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>(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
219 void
copy_test()220 copy_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(i, c, d) = make_tuple(1, 'a', 5.5);
242
243 BOOST_CHECK(i==1);
244 BOOST_CHECK(c=='a');
245 BOOST_CHECK(d>5.4 && d<5.6);
246 }
247
248 void
mutate_test()249 mutate_test()
250 {
251 tuple<int, float, bool, foo> t1(5, 12.2f, true, foo(4));
252 get<0>(t1) = 6;
253 get<1>(t1) = 2.2f;
254 get<2>(t1) = false;
255 get<3>(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
267 void
make_tuple_test()268 make_tuple_test()
269 {
270 tuple<int, char> t1 = make_tuple(5, '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((short int)2, 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(boost::cref(a), b);
283 make_tuple(boost::ref(a), b);
284 make_tuple(boost::ref(a), boost::cref(b));
285
286 make_tuple(boost::ref(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("Donald", "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(&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
329 void
tie_test()330 tie_test()
331 {
332 int a;
333 char b;
334 foo c(5);
335
336 tie(a, b, c) = make_tuple(2, 'a', foo(3));
337 BOOST_CHECK(a == 2);
338 BOOST_CHECK(b == 'a');
339 BOOST_CHECK(c == foo(3));
340
341 tie(a, tuples::ignore, c) = make_tuple((short int)5, false, 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 (i, j) = std::make_pair(1, 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
364 void
equality_test()365 equality_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
383 void
ordering_test()384 ordering_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 // ----------------------------------------------------------------------------
cons_test()404 void 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 // ----------------------------------------------------------------------------
const_tuple_test()422 void const_tuple_test()
423 {
424 const tuple<int, float> t1(5, 3.3f);
425 BOOST_CHECK(get<0>(t1) == 5);
426 BOOST_CHECK(get<1>(t1) == 3.3f);
427 }
428
429 // ----------------------------------------------------------------------------
430 // - testing length -----------------------------------------------------------
431 // ----------------------------------------------------------------------------
tuple_length_test()432 void 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 // ----------------------------------------------------------------------------
tuple_swap_test()450 void tuple_swap_test()
451 {
452 tuple<int, float, double> t1(1, 2.0f, 3.0), t2(4, 5.0f, 6.0);
453 swap(t1, 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(t3, t4);
464 BOOST_CHECK(i == 2);
465 BOOST_CHECK(j == 1);
466 }
467
468
469
470 // ----------------------------------------------------------------------------
471 // - main ---------------------------------------------------------------------
472 // ----------------------------------------------------------------------------
473
main()474 int 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