From b4f05902b8fd77eb7a111c04d0a6834eeb26e144 Mon Sep 17 00:00:00 2001 From: K-ballo Date: Fri, 22 Aug 2014 18:50:32 -0300 Subject: [PATCH] Ported documentation to boostbook --- doc/Jamfile.v2 | 31 ++ doc/design_decisions_rationale.html | 155 -------- doc/design_decisions_rationale.qbk | 190 ++++++++++ doc/tuple_advanced_interface.html | 134 ------- doc/tuple_advanced_interface.qbk | 159 +++++++++ doc/tuple_users_guide.html | 535 ---------------------------- doc/tuple_users_guide.qbk | 525 +++++++++++++++++++++++++++ index.html | 4 +- 8 files changed, 907 insertions(+), 826 deletions(-) create mode 100644 doc/Jamfile.v2 delete mode 100644 doc/design_decisions_rationale.html create mode 100644 doc/design_decisions_rationale.qbk delete mode 100644 doc/tuple_advanced_interface.html create mode 100644 doc/tuple_advanced_interface.qbk delete mode 100644 doc/tuple_users_guide.html create mode 100644 doc/tuple_users_guide.qbk diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 new file mode 100644 index 0000000..738a112 --- /dev/null +++ b/doc/Jamfile.v2 @@ -0,0 +1,31 @@ +# Copyright (c) 2001 Jaakko Järvi + +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +project doc/tuple ; + +import boostbook ; +import quickbook ; + +xml tuple : tuple_users_guide.qbk ; + +boostbook standalone_tuple + : + tuple + : + boost.root=../../../.. + # File name of HTML output: + root.filename=tuple_users_guide + # How far down we chunk nested sections, basically all of them: + chunk.section.depth=0 + # Don't put the first section on the same page as the TOC: + chunk.first.sections=0 + # How far down sections get TOC's + toc.section.depth=1 + # Max depth in each TOC: + toc.max.depth=1 + # How far down we go with TOC's + generate.section.toc.level=0 + ; diff --git a/doc/design_decisions_rationale.html b/doc/design_decisions_rationale.html deleted file mode 100644 index 21f7457..0000000 --- a/doc/design_decisions_rationale.html +++ /dev/null @@ -1,155 +0,0 @@ - - - -Design decisions rationale for Boost Tuple Library - - - -C++ Boost - -

Tuple Library : design decisions rationale

- -

About namespaces

- -

-There was a discussion about whether tuples should be in a separate namespace or directly in the boost namespace. -The common principle is that domain libraries (like graph, python) should be on a separate -subnamespace, while utility like libraries directly in the boost namespace. -Tuples are somewhere in between, as the tuple template is clearly a general utility, but the library introduces quite a lot of names in addition to just the tuple template. -Tuples were originally under a subnamespace. -As a result of the discussion, tuple definitions were moved directly under the boost namespace. -As a result of a continued discussion, the subnamespace was reintroduced. -The final (I truly hope so) solution is now to have all definitions in namespace ::boost::tuples, and the most common names in the ::boost namespace as well. -This is accomplished with using declarations (suggested by Dave Abrahams):

-
namespace boost {
-  namespace tuples {
-      ...      
-    // All library code
-      ...
-  }
-  using tuples::tuple; 
-  using tuples::make_tuple;
-  using tuples::tie;
-  using tuples::get;
-}
-
-

With this arrangement, tuple creation with direct constructor calls, make_tuple or tie functions do not need the namespace qualifier. -Further, all functions that manipulate tuples are found with Koenig-lookup. -The only exceptions are the get<N> functions, which are always called with an explicitly qualified template argument, and thus Koenig-lookup does not apply. -Therefore, get is lifted to ::boost namespace with a using declaration. -Hence, the interface for an application programmer is in practice under the namespace ::boost. -

-

-The other names, forming an interface for library writers (cons lists, metafunctions manipulating cons lists, ...) remain in the subnamespace ::boost::tuples. -Note, that the names ignore, set_open, set_close and set_delimiter are considered to be part of the application programmer's interface, but are still not under boost namespace. -The reason being the danger for name clashes for these common names. -Further, the usage of these features is probably not very frequent. -

- -

For those who are really interested in namespaces

- -

-The subnamespace name tuples raised some discussion. -The rationale for not using the most natural name 'tuple' is to avoid having an identical name with the tuple template. -Namespace names are, however, not generally in plural form in boost libraries. -First, no real trouble was reported for using the same name for a namespace and a class and we considered changing the name 'tuples' to 'tuple'. -But we found some trouble after all. -Both gcc and edg compilers reject using declarations where the namespace and class names are identical:

- -
namespace boost {
-  namespace tuple {
-    ... tie(...);
-    class tuple; 
-      ...
-  }
-  using tuple::tie; // ok
-  using tuple::tuple; // error
-    ...
-}
-
- -

Note, however, that a corresponding using declaration in the global namespace seems to be ok:

- -

-using boost::tuple::tuple; // ok;
-
- - -

The end mark of the cons list (nil, null_type, ...)

- -

-Tuples are internally represented as cons lists: - -

tuple<int, int>
-
-

inherits from

-
cons<int, cons<int, null_type> >
-
- -

-null_type is the end mark of the list. Original proposition was nil, but the name is used in MacOS, and might have caused problems, so null_type was chosen instead. -Other names considered were null_t and unit (the empty tuple type in SML).

-

-Note that null_type is the internal representation of an empty tuple: tuple<> inherits from null_type. -

- -

Element indexing

- -

-Whether to use 0- or 1-based indexing was discussed more than thoroughly, and the following observations were made:

- -
    -
  • 0-based indexing is 'the C++ way' and used with arrays etc.
  • -
  • 1-based 'name like' indexing exists as well, eg. bind1st, bind2nd, pair::first, etc.
  • -
-

Tuple access with the syntax get<N>(a), or a.get<N>() (where a is a tuple and N an index), was considered to be of the first category, hence, the index of the first element in a tuple is 0.

- -

-A suggestion to provide 1-based 'name like' indexing with constants like _1st, _2nd, _3rd, ... was made. -By suitably chosen constant types, this would allow alternative syntaxes: - -

a.get<0>() == a.get(_1st) == a[_1st] == a(_1st);
-
- -

We chose not to provide more than one indexing method for the following reasons:

-
    -
  • 0-based indexing might not please everyone, but once its fixed, it is less confusing than having two different methods (would anyone want such constants for arrays?).
  • -
  • Adding the other indexing scheme doesn't really provide anything new (like a new feature) to the user of the library.
  • -
  • C++ variable and constant naming rules don't give many possibilities for defining short and nice index constants (like _1st, ...). -Let the binding and lambda libraries use these for a better purpose.
  • -
  • The access syntax a[_1st] (or a(_1st)) is appealing, and almost made us add the index constants after all. However, 0-based subscripting is so deep in C++, that we had a fear for confusion.
  • -
  • -Such constants are easy to add. -
  • -
- - -

Tuple comparison

- -

The comparison operator implements lexicographical order. -Other orderings were considered, mainly dominance (a < b iff for each i a(i) < b(i)). -Our belief is, that lexicographical ordering, though not mathematically the most natural one, is the most frequently needed ordering in everyday programming.

- -

Streaming

- -

-The characters specified with tuple stream manipulators are stored within the space allocated by ios_base::xalloc, which allocates storage for long type objects. -static_cast is used in casting between long and the stream's character type. -Streams that have character types not convertible back and forth to long thus fail to compile.

- -

This may be revisited at some point. The two possible solutions are:

-
    -
  • Allow only plain char types as the tuple delimiters and use widen and narrow to convert between the real character type of the stream. -This would always compile, but some calls to set manipulators might result in a different - character than expected (some default character).
  • -
  • Allocate enough space to hold the real character type of the stream. -This means memory for holding the delimiter characters must be allocated separately, and that pointers to this memory are stored in the space allocated with ios_base::xalloc. -Any volunteers?
  • -
- -Back to the user's guide -

© Copyright Jaakko Järvi 2001. - - - diff --git a/doc/design_decisions_rationale.qbk b/doc/design_decisions_rationale.qbk new file mode 100644 index 0000000..a8f4e6d --- /dev/null +++ b/doc/design_decisions_rationale.qbk @@ -0,0 +1,190 @@ +[/ + / Copyright (c) 2001 Jaakko Järvi + / + / Distributed under the Boost Software License, Version 1.0. (See + / accompanying file LICENSE_1_0.txt or copy at + / http://www.boost.org/LICENSE_1_0.txt) + /] + +[article Design decisions rationale + [quickbook 1.6] + [id design_decisions_rationale] + [copyright 2001 Jaakko J\u00E4rvi] + [license Distributed under the + [@http://boost.org/LICENSE_1_0.txt Boost Software License, + Version 1.0]. + ] +] + +[template simplesect[title] +[block ''''''[title]'''''']] + +[template endsimplesect[] +[block '''''']] + +[section About namespaces] + +There was a discussion about whether tuples should be in a separate namespace +or directly in the `boost` namespace. The common principle is that domain +libraries (like /graph/, /python/) should be on a separate subnamespace, while +utility like libraries directly in the boost namespace. Tuples are somewhere +in between, as the tuple template is clearly a general utility, but the +library introduces quite a lot of names in addition to just the tuple template. +Tuples were originally under a subnamespace. As a result of the discussion, +tuple definitions were moved directly under the `boost` namespace. As a result +of a continued discussion, the subnamespace was reintroduced. The final (I +truly hope so) solution is now to have all definitions in namespace +`::boost::tuples`, and the most common names in the `::boost` namespace as well. +This is accomplished with using declarations (suggested by Dave Abrahams): + + namespace boost { + namespace tuples { + ... + // All library code + ... + } + using tuples::tuple; + using tuples::make_tuple; + using tuples::tie; + using tuples::get; + } + +With this arrangement, tuple creation with direct constructor calls, +`make_tuple` or `tie` functions do not need the namespace qualifier. Further, +all functions that manipulate tuples are found with Koenig-lookup. The only +exceptions are the `get` functions, which are always called with an +explicitly qualified template argument, and thus Koenig-lookup does not apply. +Therefore, `get` is lifted to `::boost` namespace with a using declaration. +Hence, the interface for an application programmer is in practice under the +namespace `::boost`. + +The other names, forming an interface for library writers (cons lists, +metafunctions manipulating cons lists, ...) remain in the subnamespace +`::boost::tuples`. Note, that the names `ignore`, `set_open`, `set_close` and +`set_delimiter` are considered to be part of the application programmer's +interface, but are still not under `boost` namespace. The reason being the +danger for name clashes for these common names. Further, the usage of these +features is probably not very frequent. + +[section For those who are really interested in namespaces] + +The subnamespace name /tuples/ raised some discussion. The rationale for not +using the most natural name 'tuple' is to avoid having an identical name with +the tuple template. Namespace names are, however, not generally in plural form +in Boost libraries. First, no real trouble was reported for using the same +name for a namespace and a class and we considered changing the name 'tuples' +to 'tuple'. But we found some trouble after all. Both gcc and edg compilers +reject using declarations where the namespace and class names are identical: + + namespace boost { + namespace tuple { + ... tie(...); + class tuple; + ... + } + using tuple::tie; // ok + using tuple::tuple; // error + ... + } + +Note, however, that a corresponding using declaration in the global namespace +seems to be ok: + + using boost::tuple::tuple; // ok; + +[endsect] + +[endsect] + +[section The end mark of the cons list (`nil`, `null_type`, ...)] + +Tuples are internally represented as cons lists: + + tuple + +inherits from + + cons > + +`null_type` is the end mark of the list. Original proposition was `nil`, but +the name is used in MacOS, and might have caused problems, so `null_type` was +chosen instead. Other names considered were /null_t/ and /unit/ (the empty +tuple type in SML). + +Note that `null_type` is the internal representation of an empty tuple: +`tuple<>` inherits from `null_type`. + +[endsect] + +[section Element indexing] + +Whether to use `0`- or `1`-based indexing was discussed more than thoroughly, +and the following observations were made: + +* `0`-based indexing is 'the C++ way' and used with arrays etc. + +* `1`-based 'name like' indexing exists as well, eg. `bind1st`, `bind2nd`, + `pair::first`, etc. + +Tuple access with the syntax `get(a)`, or `a.get()` (where `a` is a +tuple and `N` an index), was considered to be of the first category, hence, +the index of the first element in a tuple is `0`. + +A suggestion to provide `1`-based 'name like' indexing with constants like +`_1st`, `_2nd`, `_3rd`, ... was made. By suitably chosen constant types, this +would allow alternative syntaxes: + + a.get<0>() == a.get(_1st) == a[_1st] == a(_1st); + +We chose not to provide more than one indexing method for the following +reasons: + +* `0`-based indexing might not please everyone, but once its fixed, it is less + confusing than having two different methods (would anyone want such + constants for arrays?). + +* Adding the other indexing scheme doesn't really provide anything new (like a + new feature) to the user of the library. + +* C++ variable and constant naming rules don't give many possibilities for + defining short and nice index constants (like `_1st`, ...). Let the binding + and lambda libraries use these for a better purpose. + +* The access syntax a[_1st] (or a(_1st)) is appealing, and almost made us add + the index constants after all. However, `0`-based subscripting is so deep in + C++, that we had a fear for confusion. + +* Such constants are easy to add. + +[endsect] + +[section Tuple comparison] + +The comparison operator implements lexicographical order. Other orderings were +considered, mainly dominance /(a < b iff for each i a(i) < b(i))/. Our belief +is, that lexicographical ordering, though not mathematically the most natural +one, is the most frequently needed ordering in everyday programming. + +[endsect] + +[section Streaming] + +The characters specified with tuple stream manipulators are stored within the +space allocated by `ios_base::xalloc`, which allocates storage for `long` type +objects. `static_cast` is used in casting between `long` and the stream's +character type. Streams that have character types not convertible back and +forth to long thus fail to compile. + +This may be revisited at some point. The two possible solutions are: + +* Allow only plain `char` types as the tuple delimiters and use `widen` and + `narrow` to convert between the real character type of the stream. This + would always compile, but some calls to set manipulators might result in a + different character than expected (some default character). + +* Allocate enough space to hold the real character type of the stream. This + means memory for holding the delimiter characters must be allocated + separately, and that pointers to this memory are stored in the space + allocated with `ios_base::xalloc`. Any volunteers? + +[endsect] diff --git a/doc/tuple_advanced_interface.html b/doc/tuple_advanced_interface.html deleted file mode 100644 index c783f02..0000000 --- a/doc/tuple_advanced_interface.html +++ /dev/null @@ -1,134 +0,0 @@ - - - - Tuple library advanced features - - - - -C++ Boost - -

Tuple library advanced features

- -The advanced features described in this document are all under namespace ::boost::tuples - -

Metafunctions for tuple types

-

-Suppose T is a tuple type, and N is a constant integral expression.

- -
element<N, T>::type
- -

gives the type of the Nth element in the tuple type T. If T is const, the resulting type is const qualified as well. -Note that the constness of T does not affect reference type -elements. -

- -
length<T>::value
- -

gives the length of the tuple type T. -

- -

Cons lists

- -

-Tuples are internally represented as cons lists. -For example, the tuple

- -
tuple<A, B, C, D>
- -

inherits from the type

-
cons<A, cons<B, cons<C, cons<D, null_type> > > >
-
- -

The tuple template provides the typedef inherited to access the cons list representation. E.g.: -tuple<A>::inherited is the type cons<A, null_type>. -

- -

Empty tuple

-

-The internal representation of the empty tuple tuple<> is null_type. -

- -

Head and tail

-

-Both tuple template and the cons templates provide the typedefs head_type and tail_type. -The head_type typedef gives the type of the first element of the tuple (or the cons list). -The -tail_type typedef gives the remaining cons list after removing the first element. -The head element is stored in the member variable head and the tail list in the member variable tail. -Cons lists provide the member function get_head() for getting a reference to the head of a cons list, and get_tail() for getting a reference to the tail. -There are const and non-const versions of both functions. -

-

-Note that in a one element tuple, tail_type equals null_type and the get_tail() function returns an object of type null_type. -

-

-The empty tuple (null_type) has no head or tail, hence the get_head and get_tail functions are not provided. -

- -

-Treating tuples as cons lists gives a convenient means to define generic functions to manipulate tuples. For example, the following pair of function templates assign 0 to each element of a tuple (obviously, the assignments must be valid operations for the element types): - -

inline void set_to_zero(const null_type&) {};
-
-template <class H, class T>
-inline void set_to_zero(cons<H, T>& x) { x.get_head() = 0; set_to_zero(x.get_tail()); }
-
-

- -

Constructing cons lists

- -

-A cons list can be default constructed provided that all its elements can be default constructed. -

-

-A cons list can be constructed from its head and tail. The prototype of the constructor is:

-
cons(typename access_traits<head_type>::parameter_type h,
-     const tail_type& t)
-
-

The traits template for the head parameter selects correct parameter types for different kinds of element types (for reference elements the parameter type equals the element type, for non-reference types the parameter type is a reference to const non-volatile element type). -

-

-For a one-element cons list the tail argument (null_type) can be omitted. -

- - -

Traits classes for tuple element types

- -

access_traits

-

-The template access_traits defines three type functions. Let T be a type of an element in a tuple:

-
    -
  1. access_traits<T>::non_const_type maps T to the return type of the non-const access functions (nonmember and member get functions, and the get_head function).
  2. -
  3. access_traits<T>::const_type maps T to the return type of the const access functions.
  4. -
  5. access_traits<T>::parameter_type maps T to the parameter type of the tuple constructor.
  6. -
-

make_tuple_traits

- -

The element types of the tuples that are created with the make_tuple functions are computed with the type function make_tuple_traits. -The type function call make_tuple_traits<T>::type implements the following type mapping:

-
    -
  • any reference type -> compile time error -
  • -
  • any array type -> constant reference to the array type -
  • -
  • reference_wrapper<T> -> T& -
  • -
  • T -> T -
  • -
- -

Objects of type reference_wrapper are created with the ref and cref functions (see The make_tuple function.) -

- -

Reference wrappers were originally part of the tuple library, but they are now a general utility of boost. -The reference_wrapper template and the ref and cref functions are defined in a separate file ref.hpp in the main boost include directory; and directly in the boost namespace. -

- -Back to the user's guide -
- -

© Copyright Jaakko Järvi 2001.

- - diff --git a/doc/tuple_advanced_interface.qbk b/doc/tuple_advanced_interface.qbk new file mode 100644 index 0000000..051e0ca --- /dev/null +++ b/doc/tuple_advanced_interface.qbk @@ -0,0 +1,159 @@ +[/ + / Copyright (c) 2001 Jaakko Järvi + / + / Distributed under the Boost Software License, Version 1.0. (See + / accompanying file LICENSE_1_0.txt or copy at + / http://www.boost.org/LICENSE_1_0.txt) + /] + +[article Tuple library advanced features + [quickbook 1.6] + [id tuple_advanced_interface] + [copyright 2001 Jaakko J\u00E4rvi] + [license Distributed under the + [@http://boost.org/LICENSE_1_0.txt Boost Software License, + Version 1.0]. + ] +] + +[template simplesect[title] +[block ''''''[title]'''''']] + +[template endsimplesect[] +[block '''''']] + +The advanced features described in this document are all under namespace +`::boost::tuples` + +[section Metafunctions for tuple types] + +Suppose `T` is a tuple type, and `N` is a constant integral expression. + + element::type + +gives the type of the `N`-th element in the tuple type `T`. If `T` is `const`, +the resulting type is `const` qualified as well. Note that the constness of `T` +does not affect reference type elements. + + length::value + +gives the length of the tuple type `T`. + +[endsect] + +[section Cons lists] + +Tuples are internally represented as /cons lists/. For example, the tuple + + tuple + +inherits from the type + + cons > > > + +The tuple template provides the typedef inherited to access the cons list +representation. E.g.: `tuple::inherited` is the type `cons`. + +[section Empty tuple] + +The internal representation of the empty tuple `tuple<>` is `null_type`. + +[endsect] + +[section Head and tail] + +Both tuple template and the cons templates provide the typedefs `head_type` +and `tail_type`. The `head_type` typedef gives the type of the first element +of the tuple (or the cons list). The `tail_type` typedef gives the remaining +cons list after removing the first element. The head element is stored in the +member variable `head` and the tail list in the member variable `tail`. Cons +lists provide the member function `get_head()` for getting a reference to the +head of a cons list, and `get_tail()` for getting a reference to the tail. +There are const and non-const versions of both functions. + +Note that in a one element tuple, `tail_type` equals `null_type` and the +`get_tail()` function returns an object of type `null_type`. + +The empty tuple (`null_type`) has no head or tail, hence the `get_head` and +`get_tail` functions are not provided. + +Treating tuples as cons lists gives a convenient means to define generic +functions to manipulate tuples. For example, the following pair of function +templates assign `0` to each element of a tuple (obviously, the assignments +must be valid operations for the element types): + + inline void set_to_zero(const null_type&) {}; + + template + inline void set_to_zero(cons& x) { x.get_head() = 0; set_to_zero(x.get_tail()); } + +[endsect] + +[section Constructing cons lists] + +A cons list can be default constructed provided that all its elements can be +default constructed. + +A cons list can be constructed from its head and tail. The prototype of the +constructor is: + + cons(typename access_traits::parameter_type h, const tail_type& t) + +The traits template for the head parameter selects correct parameter types for +different kinds of element types (for reference elements the parameter type +equals the element type, for non-reference types the parameter type is a +reference to const non-volatile element type). + +For a one-element cons list the tail argument (`null_type`) can be omitted. + +[endsect] + +[endsect] + +[section Traits classes for tuple element types] + +[section access_traits] + +The template `access_traits` defines three type functions. Let `T` be a type +of an element in a tuple: + +* `access_traits::non_const_type` maps `T` to the return type of the no + n-const access functions (nonmember and member `get` functions, and the + `get_head` function). + +* `access_traits::const_type` maps `T` to the return type of the const + access functions. + +* `access_traits::parameter_type` maps `T` to the parameter type of the + tuple constructor. + +[endsect] + +[section make_tuple_traits] + +The element types of the tuples that are created with the `make_tuple` +functions are computed with the type function `make_tuple_traits`. The type +function call `make_tuple_traits::type` implements the following type +mapping: + +* /any reference type/ -> /compile time error/ + +* /any array type/ -> /constant reference to the array type/ + +* `reference_wrapper` -> `T&` + +* `T` -> `T` + +Objects of type `reference_wrapper` are created with the `ref` and `cref` +functions (see [link tuple.constructing_tuples.make_tuple The `make_tuple` +function]). + +Reference wrappers were originally part of the tuple library, but they are now +a general utility of boost. The `reference_wrapper` template and the `ref` and +`cref` functions are defined in a separate file +[@boost:/libs/core/doc/html/core/ref.html `ref.hpp`] in the main boost include +directory; and directly in the `boost` namespace. + +[endsect] + +[endsect] diff --git a/doc/tuple_users_guide.html b/doc/tuple_users_guide.html deleted file mode 100644 index c68edfc..0000000 --- a/doc/tuple_users_guide.html +++ /dev/null @@ -1,535 +0,0 @@ - - - -The Boost Tuple Library - - - -C++ Boost - -

The Boost Tuple Library

- -

-A tuple (or n-tuple) is a fixed size collection of elements. -Pairs, triples, quadruples etc. are tuples. -In a programming language, a tuple is a data object containing other objects as elements. -These element objects may be of different types. -

- -

Tuples are convenient in many circumstances. -For instance, tuples make it easy to define functions that return more than one value. -

- -

-Some programming languages, such as ML, Python and Haskell, have built-in tuple constructs. -Unfortunately C++ does not. -To compensate for this "deficiency", the Boost Tuple Library implements a tuple construct using templates. -

- -

Table of Contents

- -
    -
  1. Using the library
  2. -
  3. Tuple types
  4. -
  5. Constructing tuples
  6. -
  7. Accessing tuple elements
  8. -
  9. Copy construction and tuple assignment
  10. -
  11. Relational operators
  12. -
  13. Tiers
  14. -
  15. Streaming
  16. -
  17. Performance
  18. -
  19. Portability
  20. -
  21. Acknowledgements
  22. -
  23. References
  24. -
- -

More details

- -

-Advanced features (describes some metafunctions etc.).

-

-Rationale behind some design/implementation decisions.

- - -

Using the library

- -

To use the library, just include:

- -
#include "boost/tuple/tuple.hpp"
- -

Comparison operators can be included with:

-
#include "boost/tuple/tuple_comparison.hpp"
- -

To use tuple input and output operators,

- -
#include "boost/tuple/tuple_io.hpp"
- -

Both tuple_io.hpp and tuple_comparison.hpp include tuple.hpp.

- -

All definitions are in namespace ::boost::tuples, but the most common names are lifted to namespace -::boost with using declarations. These names are: tuple, make_tuple, tie and get. -Further, ref and cref are defined directly under the ::boost namespace.

- -

Tuple types

- -

A tuple type is an instantiation of the tuple template. -The template parameters specify the types of the tuple elements. -The current version supports tuples with 0-10 elements. -If necessary, the upper limit can be increased up to, say, a few dozen elements. -The data element can be any C++ type. -Note that void and plain function types are valid -C++ types, but objects of such types cannot exist. -Hence, if a tuple type contains such types as elements, the tuple type -can exist, but not an object of that type. -There are natural limitations for element types that cannot -be copied, or that are not default constructible (see 'Constructing tuples' - below).

- -

-For example, the following definitions are valid tuple instantiations (A, B and C are some user defined classes):

- -
tuple<int>
-tuple<double&, const double&, const double, double*, const double*>
-tuple<A, int(*)(char, int), B(A::*)(C&), C>
-tuple<std::string, std::pair<A, B> >
-tuple<A*, tuple<const A*, const B&, C>, bool, void*>
-
- -

Constructing tuples

- -

-The tuple constructor takes the tuple elements as arguments. -For an n-element tuple, the constructor can be invoked with k arguments, where 0 <= k <= n. -For example:

-
tuple<int, double>() 
-tuple<int, double>(1) 
-tuple<int, double>(1, 3.14)
-
- -

-If no initial value for an element is provided, it is default initialized (and hence must be default initializable). -For example.

- -
class X {
-  X(); 
-public:
-  X(std::string);
-};
-
-tuple<X,X,X>()                                              // error: no default constructor for X
-tuple<X,X,X>(string("Jaba"), string("Daba"), string("Duu")) // ok
-
- -

In particular, reference types do not have a default initialization:

- -
tuple<double&>()                // error: reference must be 
-                                // initialized explicitly
-
-double d = 5; 
-tuple<double&>(d)               // ok
-
-tuple<double&>(d+3.14)          // error: cannot initialize 
-                                // non-const reference with a temporary
-
-tuple<const double&>(d+3.14)    // ok, but dangerous: 
-                                // the element becomes a dangling reference 
-
- -

Using an initial value for an element that cannot be copied, is a compile -time error:

- -
class Y { 
-  Y(const Y&); 
-public:
-  Y();
-};
-
-char a[10];
-
-tuple<char[10], Y>(a, Y()); // error, neither arrays nor Y can be copied
-tuple<char[10], Y>();       // ok
-
- -

Note particularly that the following is perfectly ok:

-
Y y;
-tuple<char(&)[10], Y&>(a, y); 
-
- -

It is possible to come up with a tuple type that cannot be constructed. -This occurs if an element that cannot be initialized has a lower -index than an element that requires initialization. -For example: tuple<char[10], int&>.

- -

In sum, the tuple construction is semantically just a group of individual elementary constructions. -

- -

The make_tuple function

- -

-Tuples can also be constructed using the make_tuple (cf. std::make_pair) helper functions. -This makes the construction more convenient, saving the programmer from explicitly specifying the element types:

-
tuple<int, int, double> add_multiply_divide(int a, int b) {
-  return make_tuple(a+b, a*b, double(a)/double(b));
-}
-
- -

-By default, the element types are deduced to the plain non-reference types. E.g.:

-
void foo(const A& a, B& b) { 
-  ...
-  make_tuple(a, b);
-
-

The make_tuple invocation results in a tuple of type tuple<A, B>.

- -

-Sometimes the plain non-reference type is not desired, e.g. if the element type cannot be copied. -Therefore, the programmer can control the type deduction and state that a reference to const or reference to -non-const type should be used as the element type instead. -This is accomplished with two helper template functions: ref and cref. -Any argument can be wrapped with these functions to get the desired type. -The mechanism does not compromise const correctness since a const object wrapped with ref results -in a tuple element with const reference type (see the fifth example below). -For example:

- -
A a; B b; const A ca = a;
-make_tuple(cref(a), b);      // creates tuple<const A&, B>
-make_tuple(ref(a), b);       // creates tuple<A&, B>
-make_tuple(ref(a), cref(b)); // creates tuple<A&, const B&>
-make_tuple(cref(ca));        // creates tuple<const A&>
-make_tuple(ref(ca));         // creates tuple<const A&>
-
- - -

-Array arguments to make_tuple functions are deduced to reference to const types by default; there is no need to wrap them with cref. For example:

-
make_tuple("Donald", "Daisy");
-
- -

This creates an object of type tuple<const char (&)[7], const char (&)[6]> -(note that the type of a string literal is an array of const characters, not const char*). -However, to get make_tuple to create a tuple with an element of a -non-const array type one must use the ref wrapper.

- -

-Function pointers are deduced to the plain non-reference type, that is, to plain function pointer. -A tuple can also hold a reference to a function, -but such a tuple cannot be constructed with make_tuple (a const qualified function type would result, which is illegal):

-
void f(int i);
-  ...
-make_tuple(&f); // tuple<void (*)(int)>
-  ...
-tuple<tuple<void (&)(int)> > a(f) // ok
-make_tuple(f);                    // not ok
-
- -

Accessing tuple elements

- -

-Tuple elements are accessed with the expression:

- -
t.get<N>()
-
-

or

-
get<N>(t)
-
-

where t is a tuple object and N is a constant integral expression specifying the index of the element to be accessed. -Depending on whether t is const or not, get returns the Nth element as a reference to const or -non-const type. -The index of the first element is 0 and thus -N must be between 0 and k-1, where k is the number of elements in the tuple. -Violations of these constraints are detected at compile time. Examples:

- -
double d = 2.7; A a;
-tuple<int, double&, const A&> t(1, d, a);
-const tuple<int, double&, const A&> ct = t;
-  ...
-int i = get<0>(t); i = t.get<0>();        // ok
-int j = get<0>(ct);                       // ok
-get<0>(t) = 5;                            // ok 
-get<0>(ct) = 5;                           // error, can't assign to const 
-  ...
-double e = get<1>(t); // ok   
-get<1>(t) = 3.14;     // ok 
-get<2>(t) = A();      // error, can't assign to const 
-A aa = get<3>(t);     // error: index out of bounds 
-  ...
-++get<0>(t);  // ok, can be used as any variable
-
- -

-Note! The member get functions are not supported with MS Visual C++ compiler. -Further, the compiler has trouble with finding the non-member get functions without an explicit namespace qualifier. -Hence, all get calls should be qualified as: tuples::get<N>(a_tuple) when writing code that should compile with MSVC++ 6.0. -

- -

Copy construction and tuple assignment

- -

-A tuple can be copy constructed from another tuple, provided that the element types are element-wise copy constructible. -Analogously, a tuple can be assigned to another tuple, provided that the element types are element-wise assignable. -For example:

- -
class A {};
-class B : public A {};
-struct C { C(); C(const B&); };
-struct D { operator C() const; };
-tuple<char, B*, B, D> t;
-  ...
-tuple<int, A*, C, C> a(t); // ok 
-a = t;                     // ok 
-
- -

In both cases, the conversions performed are: char -> int, B* -> A* (derived class pointer to base class pointer), B -> C (a user defined conversion) and D -> C (a user defined conversion).

- -

-Note that assignment is also defined from std::pair types:

- -
tuple<float, int> a = std::make_pair(1, 'a');
-
- -

Relational operators

-

-Tuples reduce the operators ==, !=, <, >, <= and >= to the corresponding elementary operators. -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. - -The equality operators for two tuples a and b are defined as:

-
    -
  • a == b iff for each i: ai == bi
  • -
  • a != b iff exists i: ai != bi
  • -
- -

The operators <, >, <= and >= implement a lexicographical ordering.

- -

-Note that an attempt to compare two tuples of different lengths results in a compile time error. -Also, the comparison operators are "short-circuited": elementary comparisons start from the first elements and are performed only until the result is clear.

- -

Examples:

- -
tuple<std::string, int, A> t1(std::string("same?"), 2, A());
-tuple<std::string, long, A> t2(std::string("same?"), 2, A());
-tuple<std::string, long, A> t3(std::string("different"), 3, A());
-
-bool operator==(A, A) { std::cout << "All the same to me..."; return true; }
-
-t1 == t2; 		// true
-t1 == t3;               // false, does not print "All the..."
-
- - -

Tiers

- -

-Tiers are tuples, where all elements are of non-const reference types. -They are constructed with a call to the tie function template (cf. make_tuple):

- -
int i; char c; double d; 
-  ...
-tie(i, c, a);
-
- -

-The above tie function creates a tuple of type tuple<int&, char&, double&>. -The same result could be achieved with the call make_tuple(ref(i), ref(c), ref(a)). -

- -

-A tuple that contains non-const references as elements can be used to 'unpack' another tuple into variables. E.g.:

- -
int i; char c; double d; 
-tie(i, c, d) = make_tuple(1,'a', 5.5);
-std::cout << i << " " <<  c << " " << d;
-
-

This code prints 1 a 5.5 to the standard output stream. - -A tuple unpacking operation like this is found for example in ML and Python. -It is convenient when calling functions which return tuples.

- -

-The tying mechanism works with std::pair templates as well:

- -
int i; char c;
-tie(i, c) = std::make_pair(1, 'a');
-
-

Ignore

-

There is also an object called ignore which allows you to ignore an element assigned by a tuple. -The idea is that a function may return a tuple, only part of which you are interested in. For example (note, that ignore is under the tuples subnamespace):

- -
char c;
-tie(tuples::ignore, c) = std::make_pair(1, 'a');
-
- -

Streaming

- -

-The global operator<< has been overloaded for std::ostream such that tuples are -output by recursively calling operator<< for each element. -

- -

-Analogously, the global operator>> has been overloaded to extract tuples from std::istream by recursively calling operator>> for each element. -

- -

-The default delimiter between the elements is space, and the tuple is enclosed -in parenthesis. -For Example: - -

tuple<float, int, std::string> a(1.0f,  2, std::string("Howdy folks!");
-
-cout << a; 
-
-

outputs the tuple as: (1.0 2 Howdy folks!)

- -

-The library defines three manipulators for changing the default behavior:

-
    -
  • set_open(char) defines the character that is output before the first -element.
  • -
  • set_close(char) defines the character that is output after the -last element.
  • -
  • set_delimiter(char) defines the delimiter character between -elements.
  • -
- -

Note, that these manipulators are defined in the tuples subnamespace. -For example:

-
cout << tuples::set_open('[') << tuples::set_close(']') << tuples::set_delimiter(',') << a; 
-
-

outputs the same tuple a as: [1.0,2,Howdy folks!]

- -

The same manipulators work with operator>> and istream as well. Suppose the cin stream contains the following data: - -

(1 2 3) [4:5]
- -

The code:

- -
tuple<int, int, int> i;
-tuple<int, int> j;
-
-cin >> i;
-cin >> tuples::set_open('[') >> tuples::set_close(']') >> tuples::set_delimiter(':');
-cin >> j;
-
- -

reads the data into the tuples i and j.

- -

-Note that extracting tuples with std::string or C-style string -elements does not generally work, since the streamed tuple representation may not be unambiguously -parseable. -

- -

Performance

- -

All tuple access and construction functions are small inlined one-liners. -Therefore, a decent compiler can eliminate any extra cost of using tuples compared to using hand-written tuple like classes. -Particularly, with a decent compiler there is no performance difference between this code:

- -
class hand_made_tuple { 
-  A a; B b; C c;
-public:
-  hand_made_tuple(const A& aa, const B& bb, const C& cc) 
-    : a(aa), b(bb), c(cc) {};
-  A& getA() { return a; };
-  B& getB() { return b; };
-  C& getC() { return c; };
-};
-
-hand_made_tuple hmt(A(), B(), C()); 
-hmt.getA(); hmt.getB(); hmt.getC();
-
- -

and this code:

- -
tuple<A, B, C> t(A(), B(), C());
-t.get<0>(); t.get<1>(); t.get<2>(); 
-
- -

Note, that there are widely used compilers (e.g. bcc 5.5.1) which fail to optimize this kind of tuple usage. -

-

-Depending on the optimizing ability of the compiler, the tier mechanism may have a small performance penalty compared to using -non-const reference parameters as a mechanism for returning multiple values from a function. -For example, suppose that the following functions f1 and f2 have equivalent functionalities:

- -
void f1(int&, double&);
-tuple<int, double> f2();
-
- -

Then, the call #1 may be slightly faster than #2 in the code below:

- -
int i; double d;
-  ...
-f1(i,d);         // #1
-tie(i,d) = f2(); // #2
-
-

See -[1, -2] - for more in-depth discussions about efficiency.

- -

Effect on Compile Time

- -

-Compiling tuples can be slow due to the excessive amount of template instantiations. -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 hand_made_tuple class above. -However, as a realistic program is likely to contain a lot of code in addition to tuple definitions, the difference is probably unnoticeable. -Compile time increases between 5 and 10 percent were measured for programs which used tuples very frequently. -With the same test programs, memory consumption of compiling increased between 22% to 27%. See -[1, -2] -for details. -

- -

Portability

- -

The library code is(?) standard C++ and thus the library works with a standard conforming compiler. -Below is a list of compilers and known problems with each compiler: -

- - - - - - - -
CompilerProblems
gcc 2.95-
edg 2.44-
Borland 5.5Can't use function pointers or member pointers as tuple elements
Metrowerks 6.2Can't use ref and cref wrappers
MS Visual C++No reference elements (tie still works). Can't use ref and cref wrappers
- -

Acknowledgements

-

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. -The comments by Vesa Karvonen, John Max Skaller, Ed Brey, Beman Dawes, David Abrahams and Hartmut Kaiser helped to improve the -library. -The idea for the tie mechanism came from an old usenet article by Ian McCulloch, where he proposed something similar for std::pairs.

-

References

- -

-[1] -Järvi J.: Tuples and multiple return values in C++, TUCS Technical Report No 249, 1999. -

- -

-[2] -Järvi J.: ML-Style Tuple Assignment in Standard C++ - Extending the Multiple Return Value Formalism, TUCS Technical Report No 267, 1999. -

- -

-[3] Järvi J.:Tuple Types and Multiple Return Values, C/C++ Users Journal, August 2001. -

- -
- -

Last modified 2003-09-07

- -

© Copyright Jaakko Järvi 2001. - -Permission to copy, use, modify, sell and distribute this software and its documentation is granted provided this copyright notice appears in all copies. -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. -

- - - - - - diff --git a/doc/tuple_users_guide.qbk b/doc/tuple_users_guide.qbk new file mode 100644 index 0000000..43d03e6 --- /dev/null +++ b/doc/tuple_users_guide.qbk @@ -0,0 +1,525 @@ +[/ + / Copyright (c) 2001 Jaakko Järvi + / + / Distributed under the Boost Software License, Version 1.0. (See + / accompanying file LICENSE_1_0.txt or copy at + / http://www.boost.org/LICENSE_1_0.txt) + /] + +[library Boost.Tuple + [quickbook 1.6] + [id tuple] + [copyright 2001 Jaakko J\u00E4rvi] + [dirname tuple] + [license Distributed under the + [@http://boost.org/LICENSE_1_0.txt Boost Software License, + Version 1.0]. + ] +] + +[include tuple_advanced_interface.qbk] +[include design_decisions_rationale.qbk] + +[template simplesect[title] +[block ''''''[title]'''''']] + +[template endsimplesect[] +[block '''''']] + +A tuple (or n-tuple) is a fixed size collection of elements. Pairs, triples, +quadruples etc. are tuples. In a programming language, a tuple is a data +object containing other objects as elements. These element objects may be of +different types. + +Tuples are convenient in many circumstances. For instance, tuples make it easy +to define functions that return more than one value. + +Some programming languages, such as ML, Python and Haskell, have built-in +tuple constructs. Unfortunately C++ does not. To compensate for this +"deficiency", the Boost Tuple Library implements a tuple construct using +templates. + +[section:using_library Using the Library] + +To use the library, just include: + + #include "boost/tuple/tuple.hpp" + +Comparison operators can be included with: + + #include "boost/tuple/tuple_comparison.hpp" + +To use tuple input and output operators, + + #include "boost/tuple/tuple_io.hpp" + +Both `tuple_io.hpp` and `tuple_comparison.hpp` include `tuple.hpp`. + +All definitions are in namespace `::boost::tuples`, but the most common names +are lifted to namespace `::boost` with using declarations. These names are: +`tuple`, `make_tuple`, `tie` and `get`. Further, `ref` and `cref` are defined +directly under the `::boost` namespace. + +[endsect] + +[section:tuple_types Tuple Types] + +A tuple type is an instantiation of the `tuple` template. The template +parameters specify the types of the tuple elements. The current version +supports tuples with 0-10 elements. If necessary, the upper limit can be +increased up to, say, a few dozen elements. The data element can be any C++ +type. Note that `void` and plain function types are valid C++ types, but +objects of such types cannot exist. Hence, if a tuple type contains such types +as elements, the tuple type can exist, but not an object of that type. There +are natural limitations for element types that cannot be copied, or that are +not default constructible (see [link tuple.constructing_tuples 'Constructing tuples'] +below). + +For example, the following definitions are valid tuple instantiations (`A`, +`B` and `C` are some user defined classes): + + tuple + tuple + tuple + tuple > + tuple, bool, void*> + +[endsect] + +[section:constructing_tuples Constructing Tuples] + +The tuple constructor takes the tuple elements as arguments. For an /n/- +element tuple, the constructor can be invoked with /k/ arguments, where +`0` <= /k/ <= /n/. For example: + + tuple() + tuple(1) + tuple(1, 3.14) + +If no initial value for an element is provided, it is default initialized +(and hence must be default initializable). For example: + + class X { + X(); + public: + X(std::string); + }; + + tuple() // error: no default constructor for X + tuple(string("Jaba"), string("Daba"), string("Duu")) // ok + +In particular, reference types do not have a default initialization: + + tuple() // error: reference must be + // initialized explicitly + + double d = 5; + tuple(d) // ok + + tuple(d+3.14) // error: cannot initialize + // non-const reference with a temporary + + tuple(d+3.14) // ok, but dangerous: + // the element becomes a dangling reference + +Using an initial value for an element that cannot be copied, is a compile time +error: + + class Y { + Y(const Y&); + public: + Y(); + }; + + char a[10]; + + tuple(a, Y()); // error, neither arrays nor Y can be copied + tuple(); // ok + +Note particularly that the following is perfectly ok: + + Y y; + tuple(a, y); + +It is possible to come up with a tuple type that cannot be constructed. This +occurs if an element that cannot be initialized has a lower index than an +element that requires initialization. For example: `tuple`. + +In sum, the tuple construction is semantically just a group of individual +elementary constructions. + +[section:make_tuple The `make_tuple` function] + +Tuples can also be constructed using the `make_tuple` (cf. `std::make_pair`) +helper functions. This makes the construction more convenient, saving the +programmer from explicitly specifying the element types: + + tuple add_multiply_divide(int a, int b) { + return make_tuple(a+b, a*b, double(a)/double(b)); + } + +By default, the element types are deduced to the plain non-reference types. +E.g.: + + void foo(const A& a, B& b) { + ... + make_tuple(a, b); + +The `make_tuple` invocation results in a tuple of type `tuple`. + +Sometimes the plain non-reference type is not desired, e.g. if the element +type cannot be copied. Therefore, the programmer can control the type +deduction and state that a reference to const or reference to non-const type +should be used as the element type instead. This is accomplished with two +helper template functions: [@boost:/libs/core/doc/html/core/ref.html `boost::ref`] +and [@boost:/libs/core/doc/html/core/ref.html `boost::cref`]. Any argument can +be wrapped with these functions to get the desired type. The mechanism does +not compromise const correctness since a const object wrapped with ref results +in a tuple element with const reference type (see the fifth example below). +For example: + + A a; B b; const A ca = a; + make_tuple(cref(a), b); // creates tuple + make_tuple(ref(a), b); // creates tuple + make_tuple(ref(a), cref(b)); // creates tuple + make_tuple(cref(ca)); // creates tuple + make_tuple(ref(ca)); // creates tuple + +Array arguments to `make_tuple` functions are deduced to reference to const +types by default; there is no need to wrap them with `cref`. For example: + + make_tuple("Donald", "Daisy"); + +This creates an object of type `tuple` +(note that the type of a string literal is an array of const characters, not +`const char*`). However, to get `make_tuple` to create a tuple with an element +of a non-const array type one must use the `ref` wrapper. + +Function pointers are deduced to the plain non-reference type, that is, to +plain function pointer. A tuple can also hold a reference to a function, but +such a tuple cannot be constructed with `make_tuple` (a const qualified +function type would result, which is illegal): + + void f(int i); + ... + make_tuple(&f); // tuple + ... + tuple > a(f) // ok + make_tuple(f); // not ok + +[endsect] + +[endsect] + +[section:accessing_elements Accessing Tuple Elements] + +Tuple elements are accessed with the expression: + + t.get() + +or + + get(t) + +where `t` is a tuple object and `N` is a constant integral expression +specifying the index of the element to be accessed. Depending on whether `t` +is const or not, `get` returns the `N`-th element as a reference to const or +non-const type. The index of the first element is `0` and thus `N` must be +between `0` and /k/`-1`, where /k/ is the number of elements in the tuple. +Violations of these constraints are detected at compile time. Examples: + + double d = 2.7; A a; + tuple t(1, d, a); + const tuple ct = t; + ... + int i = get<0>(t); i = t.get<0>(); // ok + int j = get<0>(ct); // ok + get<0>(t) = 5; // ok + get<0>(ct) = 5; // error, can't assign to const + ... + double e = get<1>(t); // ok + get<1>(t) = 3.14; // ok + get<2>(t) = A(); // error, can't assign to const + A aa = get<3>(t); // error: index out of bounds + ... + ++get<0>(t); // ok, can be used as any variable + +/[Note:/ The member `get` functions are not supported with MS Visual C++ +compiler. Further, the compiler has trouble with finding the non-member `get` +functions without an explicit namespace qualifier. Hence, all `get` calls +should be qualified as `tuples::get(a_tuple)` when writing code that should +compile with MSVC++ 6.0./]/ + +[endsect] + +[section:construction_and_assignment Copy Construction and Tuple Assignment] + +A tuple can be copy constructed from another tuple, provided that the element +types are element-wise copy constructible. Analogously, a tuple can be +assigned to another tuple, provided that the element types are element-wise +assignable. For example: + + class A {}; + class B : public A {}; + struct C { C(); C(const B&); }; + struct D { operator C() const; }; + tuple t; + ... + tuple a(t); // ok + a = t; // ok + +In both cases, the conversions performed are: + +* `char -> int`, +* `B* -> A*` (derived class pointer to base class pointer), +* `B -> C` (a user defined conversion), and +* `D -> C` (a user defined conversion). + +Note that assignment is also defined from `std::pair` types: + + tuple a = std::make_pair(1, 'a'); + +[endsect] + +[section:relational_operators Relational Operators] + +Tuples reduce the operators `==`, `!=`, `<`, `>`, `<=` and `>=` to the +corresponding elementary operators. 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. The equality operators for two tuples `a` +and `b` are defined as: + +* `a == b` iff for each `i`: `a`'''i'''` == b`'''i''' +* `a != b` iff exists `i`: `a`'''i'''` != b`'''i''' + +The operators `<`, `>`, `<=` and `>=` implement a lexicographical ordering. + +Note that an attempt to compare two tuples of different lengths results in a +compile time error. Also, the comparison operators are /"short-circuited"/: +elementary comparisons start from the first elements and are performed only +until the result is clear. + +Examples: + + tuple t1(std::string("same?"), 2, A()); + tuple t2(std::string("same?"), 2, A()); + tuple t3(std::string("different"), 3, A()); + + bool operator==(A, A) { std::cout << "All the same to me..."; return true; } + + t1 == t2; // true + t1 == t3; // false, does not print "All the..." + +[endsect] + +[section:tiers Tiers] + +/Tiers/ are tuples, where all elements are of non-const reference types. They +are constructed with a call to the `tie` function template (cf. `make_tuple`): + + int i; char c; double d; + ... + tie(i, c, a); + +The above `tie` function creates a tuple of type `tuple`. +The same result could be achieved with the call `make_tuple(ref(i), ref(c), ref(a))`. + +A tuple that contains non-const references as elements can be used to 'unpack' +another tuple into variables. E.g.: + + int i; char c; double d; + tie(i, c, d) = make_tuple(1,'a', 5.5); + std::cout << i << " " << c << " " << d; + +This code prints `1 a 5.5` to the standard output stream. A tuple unpacking +operation like this is found for example in ML and Python. It is convenient +when calling functions which return tuples. + +The tying mechanism works with `std::pair` templates as well: + + int i; char c; + tie(i, c) = std::make_pair(1, 'a'); + +[section Ignore] + +There is also an object called `ignore` which allows you to ignore an element +assigned by a tuple. The idea is that a function may return a tuple, only part +of which you are interested in. For example (note, that ignore is under the +`tuples` subnamespace): + + char c; + tie(tuples::ignore, c) = std::make_pair(1, 'a'); + +[endsect] + +[endsect] + +[section:streaming Streaming] + +The global `operator<<` has been overloaded for `std::ostream` such that +tuples are output by recursively calling `operator<<` for each element. + +Analogously, the global `operator>>` has been overloaded to extract tuples +from `std::istream` by recursively calling `operator>>` for each element. + +The default delimiter between the elements is space, and the tuple is enclosed +in parenthesis. For Example: + + tuple a(1.0f, 2, std::string("Howdy folks!"); + + cout << a; + +outputs the tuple as: `(1.0 2 Howdy folks!)` + +The library defines three manipulators for changing the default behavior: + +* `set_open(char)` defines the character that is output before the first element. +* `set_close(char)` defines the character that is output after the last element. +* `set_delimiter(char)` defines the delimiter character between elements. + +Note, that these manipulators are defined in the tuples subnamespace. For +example: + + cout << tuples::set_open('[') << tuples::set_close(']') << tuples::set_delimiter(',') << a; + +outputs the same tuple `a` as: `[1.0,2,Howdy folks!]` + +The same manipulators work with `operator>>` and `istream` as well. Suppose +the `cin` stream contains the following data: + + (1 2 3) [4:5] + +The code: + + tuple i; + tuple j; + + cin >> i; + cin >> tuples::set_open('[') >> tuples::set_close(']') >> tuples::set_delimiter(':'); + cin >> j; + +reads the data into the tuples `i` and `j`. + +Note that extracting tuples with `std::string` or C-style string elements does +not generally work, since the streamed tuple representation may not be +unambiguously parseable. + +[endsect] + +[section:performance Performance] + +All tuple access and construction functions are small inlined one-liners. +Therefore, a decent compiler can eliminate any extra cost of using tuples +compared to using hand-written tuple like classes. Particularly, with a decent +compiler there is no performance difference between this code: + + class hand_made_tuple { + A a; B b; C c; + public: + hand_made_tuple(const A& aa, const B& bb, const C& cc) + : a(aa), b(bb), c(cc) {}; + A& getA() { return a; }; + B& getB() { return b; }; + C& getC() { return c; }; + }; + + hand_made_tuple hmt(A(), B(), C()); + hmt.getA(); hmt.getB(); hmt.getC(); + +and this code: + + tuple t(A(), B(), C()); + t.get<0>(); t.get<1>(); t.get<2>(); + +Note, that there are widely used compilers (e.g. bcc 5.5.1) which fail to +optimize this kind of tuple usage. + +Depending on the optimizing ability of the compiler, the tier mechanism may +have a small performance penalty compared to using non-const reference +parameters as a mechanism for returning multiple values from a function. For +example, suppose that the following functions `f1` and `f2` have equivalent +functionalities: + + void f1(int&, double&); + tuple f2(); + +Then, the call #1 may be slightly faster than #2 in the code below: + + int i; double d; + ... + f1(i,d); // #1 + tie(i,d) = f2(); // #2 + +See [[link publ_1 1], [link publ_2 2]] for more in-depth discussions about +efficiency. + +[section Effect on Compile Time] + +Compiling tuples can be slow due to the excessive amount of template +instantiations. 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 `hand_made_tuple` class above. +However, as a realistic program is likely to contain a lot of code in addition +to tuple definitions, the difference is probably unnoticeable. Compile time +increases between 5 and 10 percent were measured for programs which used tuples +very frequently. With the same test programs, memory consumption of compiling +increased between 22% to 27%. See [[link publ_1 1], [link publ_2 2]] for +details. + +[endsect] + +[endsect] + +[section:portability Portability] + +The library code is(?) standard C++ and thus the library works with a standard +conforming compiler. Below is a list of compilers and known problems with each +compiler: + +[table + [[Compiler] [Problems]] + [[gcc 2.95] [-]] + [[edg 2.44] [-]] + [[Borland 5.5] [Can't use function pointers or member pointers as + tuple elements]] + [[Metrowerks 6.2] [Can't use `ref` and `cref` wrappers]] + [[MS Visual C++] [No reference elements (`tie` still works). Can't use + `ref` and `cref` wrappers]] +] + +[endsect] + +[section:more_details More Details] + +[link tuple_advanced_interface Advanced features] (describes some metafunctions etc.). + +[link design_decisions_rationale Rationale behind some design/implementation decisions]. + +[endsect] + +[section:thanks Acknowledgements] + +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. The +comments by Vesa Karvonen, John Max Skaller, Ed Brey, Beman Dawes, David +Abrahams and Hartmut Kaiser helped to improve the library. The idea for the +`tie` mechanism came from an old usenet article by Ian McCulloch, where he +proposed something similar for `std::pair`s. + +[endsect] + +[section:references References] + +[#publ_1] +[1] J\u00E4rvi J.: /Tuples and multiple return values in C++/, TUCS Technical Report No 249, 1999. + +[#publ_2] +[2] J\u00E4rvi J.: /ML-Style Tuple Assignment in Standard C++ - Extending the Multiple Return Value Formalism/, TUCS Technical Report No 267, 1999. + +[#publ_3] +[3] J\u00E4rvi J.: /Tuple Types and Multiple Return Values/, C/C++ Users Journal, August 2001. + +[endsect] diff --git a/index.html b/index.html index d8c1cf8..437c1e7 100644 --- a/index.html +++ b/index.html @@ -1,9 +1,9 @@ - + -Automatic redirection failed, please go to doc/tuple_users_guide.html +Automatic redirection failed, please go to doc/html/tuple_users_guide.html  

© Copyright Beman Dawes, 2001

Distributed under the Boost Software License, Version 1.0. (See accompanying