1[/ 2 / Copyright (c) 2001 Jaakko J�rvi 3 / 4 / Distributed under the Boost Software License, Version 1.0. (See 5 / accompanying file LICENSE_1_0.txt or copy at 6 / http://www.boost.org/LICENSE_1_0.txt) 7 /] 8 9[library Boost.Tuple 10 [quickbook 1.6] 11 [id tuple] 12 [copyright 2001 Jaakko J\u00E4rvi] 13 [dirname tuple] 14 [license Distributed under the 15 [@http://boost.org/LICENSE_1_0.txt Boost Software License, 16 Version 1.0]. 17 ] 18] 19 20[include tuple_advanced_interface.qbk] 21[include design_decisions_rationale.qbk] 22 23[template simplesect[title] 24[block '''<simplesect><title>'''[title]'''</title>''']] 25 26[template endsimplesect[] 27[block '''</simplesect>''']] 28 29A tuple (or n-tuple) is a fixed size collection of elements. Pairs, triples, 30quadruples etc. are tuples. In a programming language, a tuple is a data 31object containing other objects as elements. These element objects may be of 32different types. 33 34Tuples are convenient in many circumstances. For instance, tuples make it easy 35to define functions that return more than one value. 36 37Some programming languages, such as ML, Python and Haskell, have built-in 38tuple constructs. Unfortunately C++ does not. To compensate for this 39"deficiency", the Boost Tuple Library implements a tuple construct using 40templates. 41 42[section:using_library Using the Library] 43 44To use the library, just include: 45 46 #include "boost/tuple/tuple.hpp" 47 48Comparison operators can be included with: 49 50 #include "boost/tuple/tuple_comparison.hpp" 51 52To use tuple input and output operators, 53 54 #include "boost/tuple/tuple_io.hpp" 55 56Both `tuple_io.hpp` and `tuple_comparison.hpp` include `tuple.hpp`. 57 58All definitions are in namespace `::boost::tuples`, but the most common names 59are lifted to namespace `::boost` with using declarations. These names are: 60`tuple`, `make_tuple`, `tie` and `get`. Further, `ref` and `cref` are defined 61directly under the `::boost` namespace. 62 63[endsect] 64 65[section:tuple_types Tuple Types] 66 67A tuple type is an instantiation of the `tuple` template. The template 68parameters specify the types of the tuple elements. The current version 69supports tuples with 0-10 elements. If necessary, the upper limit can be 70increased up to, say, a few dozen elements. The data element can be any C++ 71type. Note that `void` and plain function types are valid C++ types, but 72objects of such types cannot exist. Hence, if a tuple type contains such types 73as elements, the tuple type can exist, but not an object of that type. There 74are natural limitations for element types that cannot be copied, or that are 75not default constructible (see [link tuple.constructing_tuples 'Constructing tuples'] 76below). 77 78For example, the following definitions are valid tuple instantiations (`A`, 79`B` and `C` are some user defined classes): 80 81 tuple<int> 82 tuple<double&, const double&, const double, double*, const double*> 83 tuple<A, int(*)(char, int), B(A::*)(C&), C> 84 tuple<std::string, std::pair<A, B> > 85 tuple<A*, tuple<const A*, const B&, C>, bool, void*> 86 87[endsect] 88 89[section:constructing_tuples Constructing Tuples] 90 91The tuple constructor takes the tuple elements as arguments. For an /n/- 92element tuple, the constructor can be invoked with /k/ arguments, where 93`0` <= /k/ <= /n/. For example: 94 95 tuple<int, double>() 96 tuple<int, double>(1) 97 tuple<int, double>(1, 3.14) 98 99If no initial value for an element is provided, it is default initialized 100(and hence must be default initializable). For example: 101 102 class X { 103 X(); 104 public: 105 X(std::string); 106 }; 107 108 tuple<X,X,X>() // error: no default constructor for X 109 tuple<X,X,X>(string("Jaba"), string("Daba"), string("Duu")) // ok 110 111In particular, reference types do not have a default initialization: 112 113 tuple<double&>() // error: reference must be 114 // initialized explicitly 115 116 double d = 5; 117 tuple<double&>(d) // ok 118 119 tuple<double&>(d+3.14) // error: cannot initialize 120 // non-const reference with a temporary 121 122 tuple<const double&>(d+3.14) // ok, but dangerous: 123 // the element becomes a dangling reference 124 125Using an initial value for an element that cannot be copied, is a compile time 126error: 127 128 class Y { 129 Y(const Y&); 130 public: 131 Y(); 132 }; 133 134 char a[10]; 135 136 tuple<char[10], Y>(a, Y()); // error, neither arrays nor Y can be copied 137 tuple<char[10], Y>(); // ok 138 139Note particularly that the following is perfectly ok: 140 141 Y y; 142 tuple<char(&)[10], Y&>(a, y); 143 144It is possible to come up with a tuple type that cannot be constructed. This 145occurs if an element that cannot be initialized has a lower index than an 146element that requires initialization. For example: `tuple<char[10], int&>`. 147 148In sum, the tuple construction is semantically just a group of individual 149elementary constructions. 150 151[section:make_tuple The `make_tuple` function] 152 153Tuples can also be constructed using the `make_tuple` (cf. `std::make_pair`) 154helper functions. This makes the construction more convenient, saving the 155programmer from explicitly specifying the element types: 156 157 tuple<int, int, double> add_multiply_divide(int a, int b) { 158 return make_tuple(a+b, a*b, double(a)/double(b)); 159 } 160 161By default, the element types are deduced to the plain non-reference types. 162E.g.: 163 164 void foo(const A& a, B& b) { 165 ... 166 make_tuple(a, b); 167 168The `make_tuple` invocation results in a tuple of type `tuple<A, B>`. 169 170Sometimes the plain non-reference type is not desired, e.g. if the element 171type cannot be copied. Therefore, the programmer can control the type 172deduction and state that a reference to const or reference to non-const type 173should be used as the element type instead. This is accomplished with two 174helper template functions: [@boost:/libs/core/doc/html/core/ref.html `boost::ref`] 175and [@boost:/libs/core/doc/html/core/ref.html `boost::cref`]. Any argument can 176be wrapped with these functions to get the desired type. The mechanism does 177not compromise const correctness since a const object wrapped with ref results 178in a tuple element with const reference type (see the fifth example below). 179For example: 180 181 A a; B b; const A ca = a; 182 make_tuple(cref(a), b); // creates tuple<const A&, B> 183 make_tuple(ref(a), b); // creates tuple<A&, B> 184 make_tuple(ref(a), cref(b)); // creates tuple<A&, const B&> 185 make_tuple(cref(ca)); // creates tuple<const A&> 186 make_tuple(ref(ca)); // creates tuple<const A&> 187 188Array arguments to `make_tuple` functions are deduced to reference to const 189types by default; there is no need to wrap them with `cref`. For example: 190 191 make_tuple("Donald", "Daisy"); 192 193This creates an object of type `tuple<const char (&)[7], const char (&)[6]>` 194(note that the type of a string literal is an array of const characters, not 195`const char*`). However, to get `make_tuple` to create a tuple with an element 196of a non-const array type one must use the `ref` wrapper. 197 198Function pointers are deduced to the plain non-reference type, that is, to 199plain function pointer. A tuple can also hold a reference to a function, but 200such a tuple cannot be constructed with `make_tuple` (a const qualified 201function type would result, which is illegal): 202 203 void f(int i); 204 ... 205 make_tuple(&f); // tuple<void (*)(int)> 206 ... 207 tuple<tuple<void (&)(int)> > a(f) // ok 208 make_tuple(f); // not ok 209 210[endsect] 211 212[endsect] 213 214[section:accessing_elements Accessing Tuple Elements] 215 216Tuple elements are accessed with the expression: 217 218 t.get<N>() 219 220or 221 222 get<N>(t) 223 224where `t` is a tuple object and `N` is a constant integral expression 225specifying the index of the element to be accessed. Depending on whether `t` 226is const or not, `get` returns the `N`-th element as a reference to const or 227non-const type. The index of the first element is `0` and thus `N` must be 228between `0` and /k/`-1`, where /k/ is the number of elements in the tuple. 229Violations of these constraints are detected at compile time. Examples: 230 231 double d = 2.7; A a; 232 tuple<int, double&, const A&> t(1, d, a); 233 const tuple<int, double&, const A&> ct = t; 234 ... 235 int i = get<0>(t); i = t.get<0>(); // ok 236 int j = get<0>(ct); // ok 237 get<0>(t) = 5; // ok 238 get<0>(ct) = 5; // error, can't assign to const 239 ... 240 double e = get<1>(t); // ok 241 get<1>(t) = 3.14; // ok 242 get<2>(t) = A(); // error, can't assign to const 243 A aa = get<3>(t); // error: index out of bounds 244 ... 245 ++get<0>(t); // ok, can be used as any variable 246 247/[Note:/ The member `get` functions are not supported with MS Visual C++ 248compiler. Further, the compiler has trouble with finding the non-member `get` 249functions without an explicit namespace qualifier. Hence, all `get` calls 250should be qualified as `tuples::get<N>(a_tuple)` when writing code that should 251compile with MSVC++ 6.0./]/ 252 253[endsect] 254 255[section:construction_and_assignment Copy Construction and Tuple Assignment] 256 257A tuple can be copy constructed from another tuple, provided that the element 258types are element-wise copy constructible. Analogously, a tuple can be 259assigned to another tuple, provided that the element types are element-wise 260assignable. For example: 261 262 class A {}; 263 class B : public A {}; 264 struct C { C(); C(const B&); }; 265 struct D { operator C() const; }; 266 tuple<char, B*, B, D> t; 267 ... 268 tuple<int, A*, C, C> a(t); // ok 269 a = t; // ok 270 271In both cases, the conversions performed are: 272 273* `char -> int`, 274* `B* -> A*` (derived class pointer to base class pointer), 275* `B -> C` (a user defined conversion), and 276* `D -> C` (a user defined conversion). 277 278Note that assignment is also defined from `std::pair` types: 279 280 tuple<float, int> a = std::make_pair(1, 'a'); 281 282[endsect] 283 284[section:relational_operators Relational Operators] 285 286Tuples reduce the operators `==`, `!=`, `<`, `>`, `<=` and `>=` to the 287corresponding elementary operators. This means, that if any of these operators 288is defined between all elements of two tuples, then the same operator is 289defined between the tuples as well. The equality operators for two tuples `a` 290and `b` are defined as: 291 292* `a == b` iff for each `i`: `a`'''<subscript>i</subscript>'''` == b`'''<subscript>i</subscript>''' 293* `a != b` iff exists `i`: `a`'''<subscript>i</subscript>'''` != b`'''<subscript>i</subscript>''' 294 295The operators `<`, `>`, `<=` and `>=` implement a lexicographical ordering. 296 297Note that an attempt to compare two tuples of different lengths results in a 298compile time error. Also, the comparison operators are /"short-circuited"/: 299elementary comparisons start from the first elements and are performed only 300until the result is clear. 301 302Examples: 303 304 tuple<std::string, int, A> t1(std::string("same?"), 2, A()); 305 tuple<std::string, long, A> t2(std::string("same?"), 2, A()); 306 tuple<std::string, long, A> t3(std::string("different"), 3, A()); 307 308 bool operator==(A, A) { std::cout << "All the same to me..."; return true; } 309 310 t1 == t2; // true 311 t1 == t3; // false, does not print "All the..." 312 313[endsect] 314 315[section:tiers Tiers] 316 317/Tiers/ are tuples, where all elements are of non-const reference types. They 318are constructed with a call to the `tie` function template (cf. `make_tuple`): 319 320 int i; char c; double d; 321 ... 322 tie(i, c, a); 323 324The above `tie` function creates a tuple of type `tuple<int&, char&, double&>`. 325The same result could be achieved with the call `make_tuple(ref(i), ref(c), ref(a))`. 326 327A tuple that contains non-const references as elements can be used to 'unpack' 328another tuple into variables. E.g.: 329 330 int i; char c; double d; 331 tie(i, c, d) = make_tuple(1,'a', 5.5); 332 std::cout << i << " " << c << " " << d; 333 334This code prints `1 a 5.5` to the standard output stream. A tuple unpacking 335operation like this is found for example in ML and Python. It is convenient 336when calling functions which return tuples. 337 338The tying mechanism works with `std::pair` templates as well: 339 340 int i; char c; 341 tie(i, c) = std::make_pair(1, 'a'); 342 343[section Ignore] 344 345There is also an object called `ignore` which allows you to ignore an element 346assigned by a tuple. The idea is that a function may return a tuple, only part 347of which you are interested in. For example (note, that ignore is under the 348`tuples` subnamespace): 349 350 char c; 351 tie(tuples::ignore, c) = std::make_pair(1, 'a'); 352 353[endsect] 354 355[endsect] 356 357[section:streaming Streaming] 358 359The global `operator<<` has been overloaded for `std::ostream` such that 360tuples are output by recursively calling `operator<<` for each element. 361 362Analogously, the global `operator>>` has been overloaded to extract tuples 363from `std::istream` by recursively calling `operator>>` for each element. 364 365The default delimiter between the elements is space, and the tuple is enclosed 366in parenthesis. For Example: 367 368 tuple<float, int, std::string> a(1.0f, 2, std::string("Howdy folks!"); 369 370 cout << a; 371 372outputs the tuple as: `(1.0 2 Howdy folks!)` 373 374The library defines three manipulators for changing the default behavior: 375 376* `set_open(char)` defines the character that is output before the first element. 377* `set_close(char)` defines the character that is output after the last element. 378* `set_delimiter(char)` defines the delimiter character between elements. 379 380Note, that these manipulators are defined in the tuples subnamespace. For 381example: 382 383 cout << tuples::set_open('[') << tuples::set_close(']') << tuples::set_delimiter(',') << a; 384 385outputs the same tuple `a` as: `[1.0,2,Howdy folks!]` 386 387The same manipulators work with `operator>>` and `istream` as well. Suppose 388the `cin` stream contains the following data: 389 390 (1 2 3) [4:5] 391 392The code: 393 394 tuple<int, int, int> i; 395 tuple<int, int> j; 396 397 cin >> i; 398 cin >> tuples::set_open('[') >> tuples::set_close(']') >> tuples::set_delimiter(':'); 399 cin >> j; 400 401reads the data into the tuples `i` and `j`. 402 403Note that extracting tuples with `std::string` or C-style string elements does 404not generally work, since the streamed tuple representation may not be 405unambiguously parseable. 406 407[endsect] 408 409[section:performance Performance] 410 411All tuple access and construction functions are small inlined one-liners. 412Therefore, a decent compiler can eliminate any extra cost of using tuples 413compared to using hand-written tuple like classes. Particularly, with a decent 414compiler there is no performance difference between this code: 415 416 class hand_made_tuple { 417 A a; B b; C c; 418 public: 419 hand_made_tuple(const A& aa, const B& bb, const C& cc) 420 : a(aa), b(bb), c(cc) {}; 421 A& getA() { return a; }; 422 B& getB() { return b; }; 423 C& getC() { return c; }; 424 }; 425 426 hand_made_tuple hmt(A(), B(), C()); 427 hmt.getA(); hmt.getB(); hmt.getC(); 428 429and this code: 430 431 tuple<A, B, C> t(A(), B(), C()); 432 t.get<0>(); t.get<1>(); t.get<2>(); 433 434Note, that there are widely used compilers (e.g. bcc 5.5.1) which fail to 435optimize this kind of tuple usage. 436 437Depending on the optimizing ability of the compiler, the tier mechanism may 438have a small performance penalty compared to using non-const reference 439parameters as a mechanism for returning multiple values from a function. For 440example, suppose that the following functions `f1` and `f2` have equivalent 441functionalities: 442 443 void f1(int&, double&); 444 tuple<int, double> f2(); 445 446Then, the call #1 may be slightly faster than #2 in the code below: 447 448 int i; double d; 449 ... 450 f1(i,d); // #1 451 tie(i,d) = f2(); // #2 452 453See [[link publ_1 1], [link publ_2 2]] for more in-depth discussions about 454efficiency. 455 456[section Effect on Compile Time] 457 458Compiling tuples can be slow due to the excessive amount of template 459instantiations. Depending on the compiler and the tuple length, it may be more 460than 10 times slower to compile a tuple construct, compared to compiling an 461equivalent explicitly written class, such as the `hand_made_tuple` class above. 462However, as a realistic program is likely to contain a lot of code in addition 463to tuple definitions, the difference is probably unnoticeable. Compile time 464increases between 5 and 10 percent were measured for programs which used tuples 465very frequently. With the same test programs, memory consumption of compiling 466increased between 22% to 27%. See [[link publ_1 1], [link publ_2 2]] for 467details. 468 469[endsect] 470 471[endsect] 472 473[section:portability Portability] 474 475The library code is(?) standard C++ and thus the library works with a standard 476conforming compiler. Below is a list of compilers and known problems with each 477compiler: 478 479[table 480 [[Compiler] [Problems]] 481 [[gcc 2.95] [-]] 482 [[edg 2.44] [-]] 483 [[Borland 5.5] [Can't use function pointers or member pointers as 484 tuple elements]] 485 [[Metrowerks 6.2] [Can't use `ref` and `cref` wrappers]] 486 [[MS Visual C++] [No reference elements (`tie` still works). Can't use 487 `ref` and `cref` wrappers]] 488] 489 490[endsect] 491 492[section:more_details More Details] 493 494[link tuple_advanced_interface Advanced features] (describes some metafunctions etc.). 495 496[link design_decisions_rationale Rationale behind some design/implementation decisions]. 497 498[endsect] 499 500[section:thanks Acknowledgements] 501 502Gary Powell has been an indispensable helping hand. In particular, stream 503manipulators for tuples were his idea. Doug Gregor came up with a working 504version for MSVC, David Abrahams found a way to get rid of most of the 505restrictions for compilers not supporting partial specialization. Thanks to 506Jeremy Siek, William Kempf and Jens Maurer for their help and suggestions. The 507comments by Vesa Karvonen, John Max Skaller, Ed Brey, Beman Dawes, David 508Abrahams and Hartmut Kaiser helped to improve the library. The idea for the 509`tie` mechanism came from an old usenet article by Ian McCulloch, where he 510proposed something similar for `std::pair`s. 511 512[endsect] 513 514[section:references References] 515 516[#publ_1] 517[1] J\u00E4rvi J.: /Tuples and multiple return values in C++/, TUCS Technical Report No 249, 1999. 518 519[#publ_2] 520[2] J\u00E4rvi J.: /ML-Style Tuple Assignment in Standard C++ - Extending the Multiple Return Value Formalism/, TUCS Technical Report No 267, 1999. 521 522[#publ_3] 523[3] J\u00E4rvi J.: /Tuple Types and Multiple Return Values/, C/C++ Users Journal, August 2001. 524 525[endsect] 526