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