Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/tuple/doc/tuple_users_guide.html @ 12

Last change on this file since 12 was 12, checked in by landauf, 18 years ago

added boost

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