1 <!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN">
4 <title>The Boost Tuple Library
</title>
6 <body bgcolor=
"#FFFFFF" text=
"#000000">
8 <IMG SRC=
"../../../boost.png"
9 ALT=
"C++ Boost" width=
"277" height=
"86">
11 <h1>The Boost Tuple Library
</h1>
14 A tuple (or
<i>n
</i>-tuple) is a fixed size collection of elements.
15 Pairs, triples, quadruples etc. are tuples.
16 In a programming language, a tuple is a data object containing other objects as elements.
17 These element objects may be of different types.
20 <p>Tuples are convenient in many circumstances.
21 For instance, tuples make it easy to define functions that return more than one value.
25 Some programming languages, such as ML, Python and Haskell, have built-in tuple constructs.
26 Unfortunately C++ does not.
27 To compensate for this
"deficiency
", the Boost Tuple Library implements a tuple construct using templates.
30 <h2>Table of Contents
</h2>
33 <li><a href =
"#using_library">Using the library
</a></li>
34 <li><a href =
"#tuple_types">Tuple types
</a></li>
35 <li><a href =
"#constructing_tuples">Constructing tuples
</a></li>
36 <li><a href =
"#accessing_elements">Accessing tuple elements
</a></li>
37 <li><a href =
"#construction_and_assignment">Copy construction and tuple assignment
</a></li>
38 <li><a href =
"#relational_operators">Relational operators
</a></li>
39 <li><a href =
"#tiers">Tiers
</a></li>
40 <li><a href =
"#streaming">Streaming
</a></li>
41 <li><a href =
"#performance">Performance
</a></li>
42 <li><a href =
"#portability">Portability
</a></li>
43 <li><a href =
"#thanks">Acknowledgements
</a></li>
44 <li><a href =
"#references">References
</a></li>
50 <a href =
"tuple_advanced_interface.html">Advanced features
</a> (describes some metafunctions etc.).
</p>
52 <a href =
"design_decisions_rationale.html">Rationale behind some design/implementation decisions.
</a></p>
55 <h2><a name=
"using_library">Using the library
</a></h2>
57 <p>To use the library, just include:
</p>
59 <pre><code>#include
"boost/tuple/tuple.hpp
"</code></pre>
61 <p>Comparison operators can be included with:
</p>
62 <pre><code>#include
"boost/tuple/tuple_comparison.hpp
"</code></pre>
64 <p>To use tuple input and output operators,
</p>
66 <pre><code>#include
"boost/tuple/tuple_io.hpp
"</code></pre>
68 <p>Both
<code>tuple_io.hpp
</code> and
<code>tuple_comparison.hpp
</code> include
<code>tuple.hpp
</code>.
</p>
70 <p>All definitions are in namespace
<code>::boost::tuples
</code>, but the most common names are lifted to namespace
71 <code>::boost
</code> with using declarations. These names are:
<code>tuple
</code>,
<code>make_tuple
</code>,
<code>tie
</code> and
<code>get
</code>.
72 Further,
<code>ref
</code> and
<code>cref
</code> are defined directly under the
<code>::boost
</code> namespace.
</p>
74 <h2><a name =
"tuple_types">Tuple types
</a></h2>
76 <p>A tuple type is an instantiation of the
<code>tuple
</code> template.
77 The template parameters specify the types of the tuple elements.
78 The current version supports tuples with
0-
10 elements.
79 If necessary, the upper limit can be increased up to, say, a few dozen elements.
80 The data element can be any C++ type.
81 Note that
<code>void
</code> and plain function types are valid
82 C++ types, but objects of such types cannot exist.
83 Hence, if a tuple type contains such types as elements, the tuple type
84 can exist, but not an object of that type.
85 There are natural limitations for element types that cannot
86 be copied, or that are not default constructible (see 'Constructing tuples'
90 For example, the following definitions are valid tuple instantiations (
<code>A
</code>,
<code>B
</code> and
<code>C
</code> are some user defined classes):
</p>
92 <pre><code>tuple
<int
>
93 tuple
<double
&, const double
&, const double, double*, const double*
>
94 tuple
<A, int(*)(char, int), B(A::*)(C
&), C
>
95 tuple
<std::string, std::pair
<A, B
> >
96 tuple
<A*, tuple
<const A*, const B
&, C
>, bool, void*
>
99 <h2><a name =
"constructing_tuples">Constructing tuples
</a></h2>
102 The tuple constructor takes the tuple elements as arguments.
103 For an
<i>n
</i>-element tuple, the constructor can be invoked with
<i>k
</i> arguments, where
0 <=
<i>k
</i> <=
<i>n
</i>.
105 <pre><code>tuple
<int, double
>()
106 tuple
<int, double
>(
1)
107 tuple
<int, double
>(
1,
3.14)
111 If no initial value for an element is provided, it is default initialized (and hence must be default initializable).
120 tuple
<X,X,X
>() // error: no default constructor for X
121 tuple
<X,X,X
>(string(
"Jaba
"), string(
"Daba
"), string(
"Duu
")) // ok
124 <p>In particular, reference types do not have a default initialization:
</p>
126 <pre><code>tuple
<double
&>() // error: reference must be
127 // initialized explicitly
130 tuple
<double
&>(d) // ok
132 tuple
<double
&>(d+
3.14) // error: cannot initialize
133 // non-const reference with a temporary
135 tuple
<const double
&>(d+
3.14) // ok, but dangerous:
136 // the element becomes a dangling reference
139 <p>Using an initial value for an element that cannot be copied, is a compile
150 tuple
<char[
10], Y
>(a, Y()); // error, neither arrays nor Y can be copied
151 tuple
<char[
10], Y
>(); // ok
154 <p>Note particularly that the following is perfectly ok:
</p>
156 tuple
<char(
&)[
10], Y
&>(a, y);
159 <p>It is possible to come up with a tuple type that cannot be constructed.
160 This occurs if an element that cannot be initialized has a lower
161 index than an element that requires initialization.
162 For example:
<code>tuple
<char[
10], int
&></code>.
</p>
164 <p>In sum, the tuple construction is semantically just a group of individual elementary constructions.
167 <h4><a name=
"make_tuple">The
<code>make_tuple
</code> function
</a></h4>
170 Tuples can also be constructed using the
<code>make_tuple
</code> (cf.
<code>std::make_pair
</code>) helper functions.
171 This makes the construction more convenient, saving the programmer from explicitly specifying the element types:
</p>
172 <pre><code>tuple
<int, int, double
> add_multiply_divide(int a, int b) {
173 return make_tuple(a+b, a*b, double(a)/double(b));
178 By default, the element types are deduced to the plain non-reference types. E.g.:
</p>
179 <pre><code>void foo(const A
& a, B
& b) {
183 <p>The
<code>make_tuple
</code> invocation results in a tuple of type
<code>tuple
<A, B
></code>.
</p>
186 Sometimes the plain non-reference type is not desired, e.g. if the element type cannot be copied.
187 Therefore, the programmer can control the type deduction and state that a reference to const or reference to
188 non-const type should be used as the element type instead.
189 This is accomplished with two helper template functions:
<code>ref
</code> and
<code>cref
</code>.
190 Any argument can be wrapped with these functions to get the desired type.
191 The mechanism does not compromise const correctness since a const object wrapped with
<code>ref
</code> results
192 in a tuple element with const reference type (see the fifth example below).
195 <pre><code>A a; B b; const A ca = a;
196 make_tuple(cref(a), b); // creates tuple
<const A
&, B
>
197 make_tuple(ref(a), b); // creates tuple
<A
&, B
>
198 make_tuple(ref(a), cref(b)); // creates tuple
<A
&, const B
&>
199 make_tuple(cref(ca)); // creates tuple
<const A
&>
200 make_tuple(ref(ca)); // creates tuple
<const A
&>
205 Array arguments to
<code>make_tuple
</code> functions are deduced to reference to const types by default; there is no need to wrap them with
<code>cref
</code>. For example:
</p>
206 <pre><code>make_tuple(
"Donald
",
"Daisy
");
209 <p>This creates an object of type
<code>tuple
<const char (
&)[
7], const char (
&)[
6]
></code>
210 (note that the type of a string literal is an array of const characters, not
<code>const char*
</code>).
211 However, to get
<code>make_tuple
</code> to create a tuple with an element of a
212 non-const array type one must use the
<code>ref
</code> wrapper.
</p>
215 Function pointers are deduced to the plain non-reference type, that is, to plain function pointer.
216 A tuple can also hold a reference to a function,
217 but such a tuple cannot be constructed with
<code>make_tuple
</code> (a const qualified function type would result, which is illegal):
</p>
218 <pre><code>void f(int i);
220 make_tuple(
&f); // tuple
<void (*)(int)
>
222 tuple
<tuple
<void (
&)(int)
> > a(f) // ok
223 make_tuple(f); // not ok
226 <h2><a name =
"accessing_elements">Accessing tuple elements
</a></h2>
229 Tuple elements are accessed with the expression:
</p>
231 <pre><code>t.get
<N
>()
234 <pre><code>get
<N
>(t)
236 <p>where
<code>t
</code> is a tuple object and
<code>N
</code> is a constant integral expression specifying the index of the element to be accessed.
237 Depending on whether
<code>t
</code> is const or not,
<code>get
</code> returns the
<code>N
</code>th element as a reference to const or
239 The index of the first element is
0 and thus
<code>
240 N
</code> must be between
0 and
<code>k-
1</code>, where
<code>k
</code> is the number of elements in the tuple.
241 Violations of these constraints are detected at compile time. Examples:
</p>
243 <pre><code>double d =
2.7; A a;
244 tuple
<int, double
&, const A
&> t(
1, d, a);
245 const tuple
<int, double
&, const A
&> ct = t;
247 int i = get
<0>(t); i = t.get
<0>(); // ok
248 int j = get
<0>(ct); // ok
249 get
<0>(t) =
5; // ok
250 get
<0>(ct) =
5; // error, can't assign to const
252 double e = get
<1>(t); // ok
253 get
<1>(t) =
3.14; // ok
254 get
<2>(t) = A(); // error, can't assign to const
255 A aa = get
<3>(t); // error: index out of bounds
257 ++get
<0>(t); // ok, can be used as any variable
261 Note! The member get functions are not supported with MS Visual C++ compiler.
262 Further, the compiler has trouble with finding the non-member get functions without an explicit namespace qualifier.
263 Hence, all
<code>get
</code> calls should be qualified as:
<code>tuples::get
<N
>(a_tuple)
</code> when writing code that should compile with MSVC++
6.0.
266 <h2><a name =
"construction_and_assignment">Copy construction and tuple assignment
</a></h2>
269 A tuple can be copy constructed from another tuple, provided that the element types are element-wise copy constructible.
270 Analogously, a tuple can be assigned to another tuple, provided that the element types are element-wise assignable.
273 <pre><code>class A {};
274 class B : public A {};
275 struct C { C(); C(const B
&); };
276 struct D { operator C() const; };
277 tuple
<char, B*, B, D
> t;
279 tuple
<int, A*, C, C
> a(t); // ok
283 <p>In both cases, the conversions performed are:
<code>char -
> int
</code>,
<code>B* -
> A*
</code> (derived class pointer to base class pointer),
<code>B -
> C
</code> (a user defined conversion) and
<code>D -
> C
</code> (a user defined conversion).
</p>
286 Note that assignment is also defined from
<code>std::pair
</code> types:
</p>
288 <pre><code>tuple
<float, int
> a = std::make_pair(
1, 'a');
291 <h2><a name =
"relational_operators">Relational operators
</a></h2>
293 Tuples reduce the operators
<code>==, !=,
<,
>,
<=
</code> and
<code>>=
</code> to the corresponding elementary operators.
294 This means, that if any of these operators is defined between all elements of two tuples, then the same operator is defined between the tuples as well.
296 The equality operators for two tuples
<code>a
</code> and
<code>b
</code> are defined as:
</p>
298 <li><code>a == b
</code> iff for each
<code>i
</code>:
<code>a
<sub>i
</sub> == b
<sub>i
</sub></code></li>
299 <li><code>a != b
</code> iff exists
<code>i
</code>:
<code>a
<sub>i
</sub> != b
<sub>i
</sub></code></li>
302 <p>The operators
<code><,
>,
<=
</code> and
<code>>=
</code> implement a lexicographical ordering.
</p>
305 Note that an attempt to compare two tuples of different lengths results in a compile time error.
306 Also, the comparison operators are
<i>"short-circuited"</i>: elementary comparisons start from the first elements and are performed only until the result is clear.
</p>
310 <pre><code>tuple
<std::string, int, A
> t1(std::string(
"same?
"),
2, A());
311 tuple
<std::string, long, A
> t2(std::string(
"same?
"),
2, A());
312 tuple
<std::string, long, A
> t3(std::string(
"different
"),
3, A());
314 bool operator==(A, A) { std::cout
<< "All the same to me...
"; return true; }
317 t1 == t3; // false, does not print
"All the...
"
321 <h2><a name =
"tiers">Tiers
</a></h2>
324 <i>Tiers
</i> are tuples, where all elements are of non-const reference types.
325 They are constructed with a call to the
<code>tie
</code> function template (cf.
<code>make_tuple
</code>):
</p>
327 <pre><code>int i; char c; double d;
333 The above
<code>tie
</code> function creates a tuple of type
<code>tuple
<int
&, char
&, double
&></code>.
334 The same result could be achieved with the call
<code>make_tuple(ref(i), ref(c), ref(a))
</code>.
338 A tuple that contains non-const references as elements can be used to 'unpack' another tuple into variables. E.g.:
</p>
340 <pre><code>int i; char c; double d;
341 tie(i, c, d) = make_tuple(
1,'a',
5.5);
342 std::cout
<< i
<< " " << c
<< " " << d;
344 <p>This code prints
<code>1 a
5.5</code> to the standard output stream.
346 A tuple unpacking operation like this is found for example in ML and Python.
347 It is convenient when calling functions which return tuples.
</p>
350 The tying mechanism works with
<code>std::pair
</code> templates as well:
</p>
352 <pre><code>int i; char c;
353 tie(i, c) = std::make_pair(
1, 'a');
356 <p>There is also an object called
<code>ignore
</code> which allows you to ignore an element assigned by a tuple.
357 The idea is that a function may return a tuple, only part of which you are interested in. For example (note, that
<code>ignore
</code> is under the
<code>tuples
</code> subnamespace):
</p>
360 tie(tuples::ignore, c) = std::make_pair(
1, 'a');
363 <h2><a name =
"streaming">Streaming
</a></h2>
366 The global
<code>operator
<<</code> has been overloaded for
<code>std::ostream
</code> such that tuples are
367 output by recursively calling
<code>operator
<<</code> for each element.
371 Analogously, the global
<code>operator
>></code> has been overloaded to extract tuples from
<code>std::istream
</code> by recursively calling
<code>operator
>></code> for each element.
375 The default delimiter between the elements is space, and the tuple is enclosed
379 <pre><code>tuple
<float, int, std::string
> a(
1.0f,
2, std::string(
"Howdy folks!
");
383 <p>outputs the tuple as:
<code>(
1.0 2 Howdy folks!)
</code></p>
386 The library defines three
<i>manipulators
</i> for changing the default behavior:
</p>
388 <li><code>set_open(char)
</code> defines the character that is output before the first
390 <li><code>set_close(char)
</code> defines the character that is output after the
392 <li><code>set_delimiter(char)
</code> defines the delimiter character between
396 <p>Note, that these manipulators are defined in the
<code>tuples
</code> subnamespace.
398 <pre><code>cout
<< tuples::set_open('[')
<< tuples::set_close(']')
<< tuples::set_delimiter(',')
<< a;
400 <p>outputs the same tuple
<code>a
</code> as:
<code>[
1.0,
2,Howdy folks!]
</code></p>
402 <p>The same manipulators work with
<code>operator
>></code> and
<code>istream
</code> as well. Suppose the
<code>cin
</code> stream contains the following data:
404 <pre><code>(
1 2 3) [
4:
5]
</code></pre>
408 <pre><code>tuple
<int, int, int
> i;
409 tuple
<int, int
> j;
412 cin
>> tuples::set_open('[')
>> tuples::set_close(']')
>> tuples::set_delimiter(':');
416 <p>reads the data into the tuples
<code>i
</code> and
<code>j
</code>.
</p>
419 Note that extracting tuples with
<code>std::string
</code> or C-style string
420 elements does not generally work, since the streamed tuple representation may not be unambiguously
424 <h2><a name =
"performance">Performance
</a></h2>
426 <p>All tuple access and construction functions are small inlined one-liners.
427 Therefore, a decent compiler can eliminate any extra cost of using tuples compared to using hand-written tuple like classes.
428 Particularly, with a decent compiler there is no performance difference between this code:
</p>
430 <pre><code>class hand_made_tuple {
433 hand_made_tuple(const A
& aa, const B
& bb, const C
& cc)
434 : a(aa), b(bb), c(cc) {};
435 A
& getA() { return a; };
436 B
& getB() { return b; };
437 C
& getC() { return c; };
440 hand_made_tuple hmt(A(), B(), C());
441 hmt.getA(); hmt.getB(); hmt.getC();
444 <p>and this code:
</p>
446 <pre><code>tuple
<A, B, C
> t(A(), B(), C());
447 t.get
<0>(); t.get
<1>(); t.get
<2>();
450 <p>Note, that there are widely used compilers (e.g. bcc
5.5.1) which fail to optimize this kind of tuple usage.
453 Depending on the optimizing ability of the compiler, the tier mechanism may have a small performance penalty compared to using
454 non-const reference parameters as a mechanism for returning multiple values from a function.
455 For example, suppose that the following functions
<code>f1
</code> and
<code>f2
</code> have equivalent functionalities:
</p>
457 <pre><code>void f1(int
&, double
&);
458 tuple
<int, double
> f2();
461 <p>Then, the call #
1 may be slightly faster than #
2 in the code below:
</p>
463 <pre><code>int i; double d;
466 tie(i,d) = f2(); // #
2
469 [
<a href=
"#publ_1">1</a>,
470 <a href=
"#publ_2">2</a>]
471 for more in-depth discussions about efficiency.
</p>
473 <h4>Effect on Compile Time
</h4>
476 Compiling tuples can be slow due to the excessive amount of template instantiations.
477 Depending on the compiler and the tuple length, it may be more than
10 times slower to compile a tuple construct, compared to compiling an equivalent explicitly written class, such as the
<code>hand_made_tuple
</code> class above.
478 However, as a realistic program is likely to contain a lot of code in addition to tuple definitions, the difference is probably unnoticeable.
479 Compile time increases between
5 and
10 percent were measured for programs which used tuples very frequently.
480 With the same test programs, memory consumption of compiling increased between
22% to
27%. See
481 [
<a href=
"#publ_1">1</a>,
482 <a href=
"#publ_2">2</a>]
486 <h2><a name =
"portability">Portability
</a></h2>
488 <p>The library code is(?) standard C++ and thus the library works with a standard conforming compiler.
489 Below is a list of compilers and known problems with each compiler:
492 <tr><td><u>Compiler
</u></td><td><u>Problems
</u></td></tr>
493 <tr><td>gcc
2.95</td><td>-
</td></tr>
494 <tr><td>edg
2.44</td><td>-
</td></tr>
495 <tr><td>Borland
5.5</td><td>Can't use function pointers or member pointers as tuple elements
</td></tr>
496 <tr><td>Metrowerks
6.2</td><td>Can't use
<code>ref
</code> and
<code>cref
</code> wrappers
</td></tr>
497 <tr><td>MS Visual C++
</td><td>No reference elements (
<code>tie
</code> still works). Can't use
<code>ref
</code> and
<code>cref
</code> wrappers
</td></tr>
500 <h2><a name =
"thanks">Acknowledgements
</a></h2>
501 <p>Gary Powell has been an indispensable helping hand. In particular, stream manipulators for tuples were his idea. Doug Gregor came up with a working version for MSVC, David Abrahams found a way to get rid of most of the restrictions for compilers not supporting partial specialization. Thanks to Jeremy Siek, William Kempf and Jens Maurer for their help and suggestions.
502 The comments by Vesa Karvonen, John Max Skaller, Ed Brey, Beman Dawes, David Abrahams and Hartmut Kaiser helped to improve the
504 The idea for the tie mechanism came from an old usenet article by Ian McCulloch, where he proposed something similar for std::pairs.
</p>
505 <h2><a name =
"references">References
</a></h2>
508 <a name=
"publ_1"></a>[
1]
509 J
ärvi J.:
<i>Tuples and multiple return values in C++
</i>, TUCS Technical Report No
249,
1999<!-- (<a href="http://www.tucs.fi/Publications">http://www.tucs.fi/Publications</a>)-->.
513 <a name=
"publ_2"></a>[
2]
514 J
ärvi J.:
<i>ML-Style Tuple Assignment in Standard C++ - Extending the Multiple Return Value Formalism
</i>, TUCS Technical Report No
267,
1999<!-- (<a href="http://www.tucs.fi/Publications">http://www.tucs.fi/Publications</a>)-->.
518 [
3] J
ärvi J.:
<i>Tuple Types and Multiple Return Values
</i>, C/C++ Users Journal, August
2001.
523 <p>Last modified
2003-
09-
07</p>
525 <p>© Copyright
<a href=
"http://www.boost.org/people/jaakko_jarvi.htm"> Jaakko J
ärvi
</a> 2001.
527 Permission to copy, use, modify, sell and distribute this software and its documentation is granted provided this copyright notice appears in all copies.
528 This software and its documentation is provided
"as is" without express or implied warranty, and with no claim as to its suitability for any purpose.