• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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