Squashed 'third_party/boostorg/tuple/' content from commit fb55aa6
Change-Id: I7b2b942d5d0a30df2c80bcb90e9bd79a86a0acdc
git-subtree-dir: third_party/boostorg/tuple
git-subtree-split: fb55aa6d4d5e6917f55dbd7aee58afde97879b85
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..3e84d7c
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,96 @@
+* text=auto !eol svneol=native#text/plain
+*.gitattributes text svneol=native#text/plain
+
+# Scriptish formats
+*.bat text svneol=native#text/plain
+*.bsh text svneol=native#text/x-beanshell
+*.cgi text svneol=native#text/plain
+*.cmd text svneol=native#text/plain
+*.js text svneol=native#text/javascript
+*.php text svneol=native#text/x-php
+*.pl text svneol=native#text/x-perl
+*.pm text svneol=native#text/x-perl
+*.py text svneol=native#text/x-python
+*.sh eol=lf svneol=LF#text/x-sh
+configure eol=lf svneol=LF#text/x-sh
+
+# Image formats
+*.bmp binary svneol=unset#image/bmp
+*.gif binary svneol=unset#image/gif
+*.ico binary svneol=unset#image/ico
+*.jpeg binary svneol=unset#image/jpeg
+*.jpg binary svneol=unset#image/jpeg
+*.png binary svneol=unset#image/png
+*.tif binary svneol=unset#image/tiff
+*.tiff binary svneol=unset#image/tiff
+*.svg text svneol=native#image/svg%2Bxml
+
+# Data formats
+*.pdf binary svneol=unset#application/pdf
+*.avi binary svneol=unset#video/avi
+*.doc binary svneol=unset#application/msword
+*.dsp text svneol=crlf#text/plain
+*.dsw text svneol=crlf#text/plain
+*.eps binary svneol=unset#application/postscript
+*.gz binary svneol=unset#application/gzip
+*.mov binary svneol=unset#video/quicktime
+*.mp3 binary svneol=unset#audio/mpeg
+*.ppt binary svneol=unset#application/vnd.ms-powerpoint
+*.ps binary svneol=unset#application/postscript
+*.psd binary svneol=unset#application/photoshop
+*.rdf binary svneol=unset#text/rdf
+*.rss text svneol=unset#text/xml
+*.rtf binary svneol=unset#text/rtf
+*.sln text svneol=native#text/plain
+*.swf binary svneol=unset#application/x-shockwave-flash
+*.tgz binary svneol=unset#application/gzip
+*.vcproj text svneol=native#text/xml
+*.vcxproj text svneol=native#text/xml
+*.vsprops text svneol=native#text/xml
+*.wav binary svneol=unset#audio/wav
+*.xls binary svneol=unset#application/vnd.ms-excel
+*.zip binary svneol=unset#application/zip
+
+# Text formats
+.htaccess text svneol=native#text/plain
+*.bbk text svneol=native#text/xml
+*.cmake text svneol=native#text/plain
+*.css text svneol=native#text/css
+*.dtd text svneol=native#text/xml
+*.htm text svneol=native#text/html
+*.html text svneol=native#text/html
+*.ini text svneol=native#text/plain
+*.log text svneol=native#text/plain
+*.mak text svneol=native#text/plain
+*.qbk text svneol=native#text/plain
+*.rst text svneol=native#text/plain
+*.sql text svneol=native#text/x-sql
+*.txt text svneol=native#text/plain
+*.xhtml text svneol=native#text/xhtml%2Bxml
+*.xml text svneol=native#text/xml
+*.xsd text svneol=native#text/xml
+*.xsl text svneol=native#text/xml
+*.xslt text svneol=native#text/xml
+*.xul text svneol=native#text/xul
+*.yml text svneol=native#text/plain
+boost-no-inspect text svneol=native#text/plain
+CHANGES text svneol=native#text/plain
+COPYING text svneol=native#text/plain
+INSTALL text svneol=native#text/plain
+Jamfile text svneol=native#text/plain
+Jamroot text svneol=native#text/plain
+Jamfile.v2 text svneol=native#text/plain
+Jamrules text svneol=native#text/plain
+Makefile* text svneol=native#text/plain
+README text svneol=native#text/plain
+TODO text svneol=native#text/plain
+
+# Code formats
+*.c text svneol=native#text/plain
+*.cpp text svneol=native#text/plain
+*.h text svneol=native#text/plain
+*.hpp text svneol=native#text/plain
+*.ipp text svneol=native#text/plain
+*.tpp text svneol=native#text/plain
+*.jam text svneol=native#text/plain
+*.java text svneol=native#text/plain
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..fd5e2f8
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,111 @@
+# Copyright 2016, 2017 Peter Dimov
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
+
+language: cpp
+
+sudo: false
+
+python: "2.7"
+
+branches:
+ only:
+ - master
+ - develop
+ - /feature\/.*/
+
+env:
+ matrix:
+ - BOGUS_JOB=true
+
+matrix:
+
+ exclude:
+ - env: BOGUS_JOB=true
+
+ include:
+ - os: linux
+ compiler: g++
+ env: TOOLSET=gcc COMPILER=g++ CXXSTD=03,11
+
+ - os: linux
+ compiler: g++-5
+ env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=03,11,14,1z
+ addons:
+ apt:
+ packages:
+ - g++-5
+ sources:
+ - ubuntu-toolchain-r-test
+
+ - os: linux
+ compiler: g++-6
+ env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=03,11,14,1z
+ addons:
+ apt:
+ packages:
+ - g++-6
+ sources:
+ - ubuntu-toolchain-r-test
+
+ - os: linux
+ compiler: g++-7
+ env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17
+ addons:
+ apt:
+ packages:
+ - g++-7
+ sources:
+ - ubuntu-toolchain-r-test
+
+ - os: linux
+ compiler: clang++
+ env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11
+
+ - os: linux
+ compiler: clang++-4.0
+ env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=03,11,14,1z
+ addons:
+ apt:
+ packages:
+ - clang-4.0
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-trusty-4.0
+
+ - os: linux
+ compiler: clang++-5.0
+ env: TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03,11,14,1z
+ addons:
+ apt:
+ packages:
+ - clang-5.0
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-trusty-5.0
+
+ - os: osx
+ compiler: clang++
+ env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z
+
+install:
+ - BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true
+ - cd ..
+ - git clone -b $BOOST_BRANCH https://github.com/boostorg/boost.git boost-root
+ - cd boost-root
+ - git submodule update --init tools/build
+ - git submodule update --init libs/config
+ - git submodule update --init tools/boostdep
+ - cp -r $TRAVIS_BUILD_DIR/* libs/tuple
+ - python tools/boostdep/depinst/depinst.py tuple
+ - ./bootstrap.sh
+ - ./b2 headers
+
+script:
+ - |-
+ echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
+ - ./b2 -j 3 libs/tuple/test toolset=$TOOLSET cxxstd=$CXXSTD
+
+notifications:
+ email:
+ on_success: always
diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2
new file mode 100644
index 0000000..04b49ac
--- /dev/null
+++ b/doc/Jamfile.v2
@@ -0,0 +1,37 @@
+# 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
+ :
+ <xsl:param>boost.root=../../../..
+ # File name of HTML output:
+ <xsl:param>root.filename=tuple_users_guide
+ # How far down we chunk nested sections, basically all of them:
+ <xsl:param>chunk.section.depth=0
+ # Don't put the first section on the same page as the TOC:
+ <xsl:param>chunk.first.sections=0
+ # How far down sections get TOC's
+ <xsl:param>toc.section.depth=1
+ # Max depth in each TOC:
+ <xsl:param>toc.max.depth=1
+ # How far down we go with TOC's
+ <xsl:param>generate.section.toc.level=0
+ ;
+
+###############################################################################
+alias boostdoc ;
+explicit boostdoc ;
+alias boostrelease : standalone_tuple ;
+explicit boostrelease ;
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 '''<simplesect><title>'''[title]'''</title>''']]
+
+[template endsimplesect[]
+[block '''</simplesect>''']]
+
+[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<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.
+
+[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<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`.
+
+[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<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.
+
+[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.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 '''<simplesect><title>'''[title]'''</title>''']]
+
+[template endsimplesect[]
+[block '''</simplesect>''']]
+
+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<N, T>::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<T>::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<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>`.
+
+[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 <class H, class T>
+ inline void set_to_zero(cons<H, T>& 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<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.
+
+[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<T>::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<T>::const_type` maps `T` to the return type of the const
+ access functions.
+
+* `access_traits<T>::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<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 [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.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 '''<simplesect><title>'''[title]'''</title>''']]
+
+[template endsimplesect[]
+[block '''</simplesect>''']]
+
+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<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*>
+
+[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<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.
+
+[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<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: [@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<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
+
+[endsect]
+
+[endsect]
+
+[section:accessing_elements 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 `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<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./]/
+
+[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<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');
+
+[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`'''<subscript>i</subscript>'''` == b`'''<subscript>i</subscript>'''
+* `a != b` iff exists `i`: `a`'''<subscript>i</subscript>'''` != b`'''<subscript>i</subscript>'''
+
+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..."
+
+[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<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');
+
+[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<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.
+
+[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<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 [[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/include/boost/tuple/detail/tuple_basic.hpp b/include/boost/tuple/detail/tuple_basic.hpp
new file mode 100644
index 0000000..879f0e9
--- /dev/null
+++ b/include/boost/tuple/detail/tuple_basic.hpp
@@ -0,0 +1,987 @@
+// tuple_basic.hpp -----------------------------------------------------
+
+// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+//
+// 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)
+
+// For more information, see http://www.boost.org
+
+// Outside help:
+// This and that, Gary Powell.
+// Fixed return types for get_head/get_tail
+// ( and other bugs ) per suggestion of Jens Maurer
+// simplified element type accessors + bug fix (Jeremy Siek)
+// Several changes/additions according to suggestions by Douglas Gregor,
+// William Kempf, Vesa Karvonen, John Max Skaller, Ed Brey, Beman Dawes,
+// David Abrahams.
+
+// Revision history:
+// 2002 05 01 Hugo Duncan: Fix for Borland after Jaakko's previous changes
+// 2002 04 18 Jaakko: tuple element types can be void or plain function
+// types, as long as no object is created.
+// Tuple objects can no hold even noncopyable types
+// such as arrays.
+// 2001 10 22 John Maddock
+// Fixes for Borland C++
+// 2001 08 30 David Abrahams
+// Added default constructor for cons<>.
+// -----------------------------------------------------------------
+
+#ifndef BOOST_TUPLE_BASIC_HPP
+#define BOOST_TUPLE_BASIC_HPP
+
+
+#include <utility> // needed for the assignment from pair to tuple
+
+#include <boost/type_traits/cv_traits.hpp>
+#include <boost/type_traits/function_traits.hpp>
+#include <boost/utility/swap.hpp>
+
+#include <boost/detail/workaround.hpp> // needed for BOOST_WORKAROUND
+
+#if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
+#endif
+
+namespace boost {
+namespace tuples {
+
+// -- null_type --------------------------------------------------------
+struct null_type {};
+
+// a helper function to provide a const null_type type temporary
+namespace detail {
+ inline const null_type cnull() { return null_type(); }
+
+
+// -- if construct ------------------------------------------------
+// Proposed by Krzysztof Czarnecki and Ulrich Eisenecker
+
+template <bool If, class Then, class Else> struct IF { typedef Then RET; };
+
+template <class Then, class Else> struct IF<false, Then, Else> {
+ typedef Else RET;
+};
+
+} // end detail
+
+// - cons forward declaration -----------------------------------------------
+template <class HT, class TT> struct cons;
+
+
+// - tuple forward declaration -----------------------------------------------
+template <
+ class T0 = null_type, class T1 = null_type, class T2 = null_type,
+ class T3 = null_type, class T4 = null_type, class T5 = null_type,
+ class T6 = null_type, class T7 = null_type, class T8 = null_type,
+ class T9 = null_type>
+class tuple;
+
+// tuple_length forward declaration
+template<class T> struct length;
+
+
+
+namespace detail {
+
+// -- generate error template, referencing to non-existing members of this
+// template is used to produce compilation errors intentionally
+template<class T>
+class generate_error;
+
+template<int N>
+struct drop_front {
+ template<class Tuple>
+ struct apply {
+ typedef BOOST_DEDUCED_TYPENAME drop_front<N-1>::BOOST_NESTED_TEMPLATE
+ apply<Tuple> next;
+ typedef BOOST_DEDUCED_TYPENAME next::type::tail_type type;
+ static const type& call(const Tuple& tup) {
+ return next::call(tup).tail;
+ }
+ };
+};
+
+template<>
+struct drop_front<0> {
+ template<class Tuple>
+ struct apply {
+ typedef Tuple type;
+ static const type& call(const Tuple& tup) {
+ return tup;
+ }
+ };
+};
+
+} // end of namespace detail
+
+
+// -cons type accessors ----------------------------------------
+// typename tuples::element<N,T>::type gets the type of the
+// Nth element ot T, first element is at index 0
+// -------------------------------------------------------
+
+#ifndef BOOST_NO_CV_SPECIALIZATIONS
+
+template<int N, class T>
+struct element
+{
+ typedef BOOST_DEDUCED_TYPENAME detail::drop_front<N>::BOOST_NESTED_TEMPLATE
+ apply<T>::type::head_type type;
+};
+
+template<int N, class T>
+struct element<N, const T>
+{
+private:
+ typedef BOOST_DEDUCED_TYPENAME detail::drop_front<N>::BOOST_NESTED_TEMPLATE
+ apply<T>::type::head_type unqualified_type;
+public:
+#if BOOST_WORKAROUND(__BORLANDC__,<0x600)
+ typedef const unqualified_type type;
+#else
+ typedef BOOST_DEDUCED_TYPENAME boost::add_const<unqualified_type>::type type;
+#endif
+};
+#else // def BOOST_NO_CV_SPECIALIZATIONS
+
+namespace detail {
+
+template<int N, class T, bool IsConst>
+struct element_impl
+{
+ typedef BOOST_DEDUCED_TYPENAME detail::drop_front<N>::BOOST_NESTED_TEMPLATE
+ apply<T>::type::head_type type;
+};
+
+template<int N, class T>
+struct element_impl<N, T, true /* IsConst */>
+{
+ typedef BOOST_DEDUCED_TYPENAME detail::drop_front<N>::BOOST_NESTED_TEMPLATE
+ apply<T>::type::head_type unqualified_type;
+ typedef const unqualified_type type;
+};
+
+} // end of namespace detail
+
+
+template<int N, class T>
+struct element:
+ public detail::element_impl<N, T, ::boost::is_const<T>::value>
+{
+};
+
+#endif
+
+
+// -get function templates -----------------------------------------------
+// Usage: get<N>(aTuple)
+
+// -- some traits classes for get functions
+
+// access traits lifted from detail namespace to be part of the interface,
+// (Joel de Guzman's suggestion). Rationale: get functions are part of the
+// interface, so should the way to express their return types be.
+
+template <class T> struct access_traits {
+ typedef const T& const_type;
+ typedef T& non_const_type;
+
+ typedef const typename boost::remove_cv<T>::type& parameter_type;
+
+// used as the tuple constructors parameter types
+// Rationale: non-reference tuple element types can be cv-qualified.
+// It should be possible to initialize such types with temporaries,
+// and when binding temporaries to references, the reference must
+// be non-volatile and const. 8.5.3. (5)
+};
+
+template <class T> struct access_traits<T&> {
+
+ typedef T& const_type;
+ typedef T& non_const_type;
+
+ typedef T& parameter_type;
+};
+
+// get function for non-const cons-lists, returns a reference to the element
+
+template<int N, class HT, class TT>
+inline typename access_traits<
+ typename element<N, cons<HT, TT> >::type
+ >::non_const_type
+get(cons<HT, TT>& c) {
+ typedef BOOST_DEDUCED_TYPENAME detail::drop_front<N>::BOOST_NESTED_TEMPLATE
+ apply<cons<HT, TT> > impl;
+ typedef BOOST_DEDUCED_TYPENAME impl::type cons_element;
+ return const_cast<cons_element&>(impl::call(c)).head;
+}
+
+// get function for const cons-lists, returns a const reference to
+// the element. If the element is a reference, returns the reference
+// as such (that is, can return a non-const reference)
+template<int N, class HT, class TT>
+inline typename access_traits<
+ typename element<N, cons<HT, TT> >::type
+ >::const_type
+get(const cons<HT, TT>& c) {
+ typedef BOOST_DEDUCED_TYPENAME detail::drop_front<N>::BOOST_NESTED_TEMPLATE
+ apply<cons<HT, TT> > impl;
+ return impl::call(c).head;
+}
+
+// -- the cons template --------------------------------------------------
+namespace detail {
+
+// These helper templates wrap void types and plain function types.
+// The reationale is to allow one to write tuple types with those types
+// as elements, even though it is not possible to instantiate such object.
+// E.g: typedef tuple<void> some_type; // ok
+// but: some_type x; // fails
+
+template <class T> class non_storeable_type {
+ non_storeable_type();
+};
+
+template <class T> struct wrap_non_storeable_type {
+ typedef typename IF<
+ ::boost::is_function<T>::value, non_storeable_type<T>, T
+ >::RET type;
+};
+template <> struct wrap_non_storeable_type<void> {
+ typedef non_storeable_type<void> type;
+};
+
+} // detail
+
+template <class HT, class TT>
+struct cons {
+
+ typedef HT head_type;
+ typedef TT tail_type;
+
+ typedef typename
+ detail::wrap_non_storeable_type<head_type>::type stored_head_type;
+
+ stored_head_type head;
+ tail_type tail;
+
+ typename access_traits<stored_head_type>::non_const_type
+ get_head() { return head; }
+
+ typename access_traits<tail_type>::non_const_type
+ get_tail() { return tail; }
+
+ typename access_traits<stored_head_type>::const_type
+ get_head() const { return head; }
+
+ typename access_traits<tail_type>::const_type
+ get_tail() const { return tail; }
+
+ cons() : head(), tail() {}
+ // cons() : head(detail::default_arg<HT>::f()), tail() {}
+
+ // the argument for head is not strictly needed, but it prevents
+ // array type elements. This is good, since array type elements
+ // cannot be supported properly in any case (no assignment,
+ // copy works only if the tails are exactly the same type, ...)
+
+ cons(typename access_traits<stored_head_type>::parameter_type h,
+ const tail_type& t)
+ : head (h), tail(t) {}
+
+ template <class T1, class T2, class T3, class T4, class T5,
+ class T6, class T7, class T8, class T9, class T10>
+ cons( T1& t1, T2& t2, T3& t3, T4& t4, T5& t5,
+ T6& t6, T7& t7, T8& t8, T9& t9, T10& t10 )
+ : head (t1),
+ tail (t2, t3, t4, t5, t6, t7, t8, t9, t10, detail::cnull())
+ {}
+
+ template <class T2, class T3, class T4, class T5,
+ class T6, class T7, class T8, class T9, class T10>
+ cons( const null_type& /*t1*/, T2& t2, T3& t3, T4& t4, T5& t5,
+ T6& t6, T7& t7, T8& t8, T9& t9, T10& t10 )
+ : head (),
+ tail (t2, t3, t4, t5, t6, t7, t8, t9, t10, detail::cnull())
+ {}
+
+
+ template <class HT2, class TT2>
+ cons( const cons<HT2, TT2>& u ) : head(u.head), tail(u.tail) {}
+
+ template <class HT2, class TT2>
+ cons& operator=( const cons<HT2, TT2>& u ) {
+ head=u.head; tail=u.tail; return *this;
+ }
+
+ // must define assignment operator explicitly, implicit version is
+ // illformed if HT is a reference (12.8. (12))
+ cons& operator=(const cons& u) {
+ head = u.head; tail = u.tail; return *this;
+ }
+
+ template <class T1, class T2>
+ cons& operator=( const std::pair<T1, T2>& u ) {
+ BOOST_STATIC_ASSERT(length<cons>::value == 2); // check length = 2
+ head = u.first; tail.head = u.second; return *this;
+ }
+
+ // get member functions (non-const and const)
+ template <int N>
+ typename access_traits<
+ typename element<N, cons<HT, TT> >::type
+ >::non_const_type
+ get() {
+ return boost::tuples::get<N>(*this); // delegate to non-member get
+ }
+
+ template <int N>
+ typename access_traits<
+ typename element<N, cons<HT, TT> >::type
+ >::const_type
+ get() const {
+ return boost::tuples::get<N>(*this); // delegate to non-member get
+ }
+};
+
+template <class HT>
+struct cons<HT, null_type> {
+
+ typedef HT head_type;
+ typedef null_type tail_type;
+ typedef cons<HT, null_type> self_type;
+
+ typedef typename
+ detail::wrap_non_storeable_type<head_type>::type stored_head_type;
+ stored_head_type head;
+
+ typename access_traits<stored_head_type>::non_const_type
+ get_head() { return head; }
+
+ null_type get_tail() { return null_type(); }
+
+ typename access_traits<stored_head_type>::const_type
+ get_head() const { return head; }
+
+ const null_type get_tail() const { return null_type(); }
+
+ // cons() : head(detail::default_arg<HT>::f()) {}
+ cons() : head() {}
+
+ cons(typename access_traits<stored_head_type>::parameter_type h,
+ const null_type& = null_type())
+ : head (h) {}
+
+ template<class T1>
+ cons(T1& t1, const null_type&, const null_type&, const null_type&,
+ const null_type&, const null_type&, const null_type&,
+ const null_type&, const null_type&, const null_type&)
+ : head (t1) {}
+
+ cons(const null_type&,
+ const null_type&, const null_type&, const null_type&,
+ const null_type&, const null_type&, const null_type&,
+ const null_type&, const null_type&, const null_type&)
+ : head () {}
+
+ template <class HT2>
+ cons( const cons<HT2, null_type>& u ) : head(u.head) {}
+
+ template <class HT2>
+ cons& operator=(const cons<HT2, null_type>& u )
+ { head = u.head; return *this; }
+
+ // must define assignment operator explicitely, implicit version
+ // is illformed if HT is a reference
+ cons& operator=(const cons& u) { head = u.head; return *this; }
+
+ template <int N>
+ typename access_traits<
+ typename element<N, self_type>::type
+ >::non_const_type
+ get() {
+ return boost::tuples::get<N>(*this);
+ }
+
+ template <int N>
+ typename access_traits<
+ typename element<N, self_type>::type
+ >::const_type
+ get() const {
+ return boost::tuples::get<N>(*this);
+ }
+
+};
+
+// templates for finding out the length of the tuple -------------------
+
+template<class T>
+struct length {
+ BOOST_STATIC_CONSTANT(int, value = 1 + length<typename T::tail_type>::value);
+};
+
+template<>
+struct length<tuple<> > {
+ BOOST_STATIC_CONSTANT(int, value = 0);
+};
+
+template<>
+struct length<tuple<> const> {
+ BOOST_STATIC_CONSTANT(int, value = 0);
+};
+
+template<>
+struct length<null_type> {
+ BOOST_STATIC_CONSTANT(int, value = 0);
+};
+
+template<>
+struct length<null_type const> {
+ BOOST_STATIC_CONSTANT(int, value = 0);
+};
+
+namespace detail {
+
+// Tuple to cons mapper --------------------------------------------------
+template <class T0, class T1, class T2, class T3, class T4,
+ class T5, class T6, class T7, class T8, class T9>
+struct map_tuple_to_cons
+{
+ typedef cons<T0,
+ typename map_tuple_to_cons<T1, T2, T3, T4, T5,
+ T6, T7, T8, T9, null_type>::type
+ > type;
+};
+
+// The empty tuple is a null_type
+template <>
+struct map_tuple_to_cons<null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type>
+{
+ typedef null_type type;
+};
+
+} // end detail
+
+// -------------------------------------------------------------------
+// -- tuple ------------------------------------------------------
+template <class T0, class T1, class T2, class T3, class T4,
+ class T5, class T6, class T7, class T8, class T9>
+
+class tuple :
+ public detail::map_tuple_to_cons<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type
+{
+public:
+ typedef typename
+ detail::map_tuple_to_cons<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type inherited;
+ typedef typename inherited::head_type head_type;
+ typedef typename inherited::tail_type tail_type;
+
+
+// access_traits<T>::parameter_type takes non-reference types as const T&
+ tuple() {}
+
+ explicit tuple(typename access_traits<T0>::parameter_type t0)
+ : inherited(t0, detail::cnull(), detail::cnull(), detail::cnull(),
+ detail::cnull(), detail::cnull(), detail::cnull(),
+ detail::cnull(), detail::cnull(), detail::cnull()) {}
+
+ tuple(typename access_traits<T0>::parameter_type t0,
+ typename access_traits<T1>::parameter_type t1)
+ : inherited(t0, t1, detail::cnull(), detail::cnull(),
+ detail::cnull(), detail::cnull(), detail::cnull(),
+ detail::cnull(), detail::cnull(), detail::cnull()) {}
+
+ tuple(typename access_traits<T0>::parameter_type t0,
+ typename access_traits<T1>::parameter_type t1,
+ typename access_traits<T2>::parameter_type t2)
+ : inherited(t0, t1, t2, detail::cnull(), detail::cnull(),
+ detail::cnull(), detail::cnull(), detail::cnull(),
+ detail::cnull(), detail::cnull()) {}
+
+ tuple(typename access_traits<T0>::parameter_type t0,
+ typename access_traits<T1>::parameter_type t1,
+ typename access_traits<T2>::parameter_type t2,
+ typename access_traits<T3>::parameter_type t3)
+ : inherited(t0, t1, t2, t3, detail::cnull(), detail::cnull(),
+ detail::cnull(), detail::cnull(), detail::cnull(),
+ detail::cnull()) {}
+
+ tuple(typename access_traits<T0>::parameter_type t0,
+ typename access_traits<T1>::parameter_type t1,
+ typename access_traits<T2>::parameter_type t2,
+ typename access_traits<T3>::parameter_type t3,
+ typename access_traits<T4>::parameter_type t4)
+ : inherited(t0, t1, t2, t3, t4, detail::cnull(), detail::cnull(),
+ detail::cnull(), detail::cnull(), detail::cnull()) {}
+
+ tuple(typename access_traits<T0>::parameter_type t0,
+ typename access_traits<T1>::parameter_type t1,
+ typename access_traits<T2>::parameter_type t2,
+ typename access_traits<T3>::parameter_type t3,
+ typename access_traits<T4>::parameter_type t4,
+ typename access_traits<T5>::parameter_type t5)
+ : inherited(t0, t1, t2, t3, t4, t5, detail::cnull(), detail::cnull(),
+ detail::cnull(), detail::cnull()) {}
+
+ tuple(typename access_traits<T0>::parameter_type t0,
+ typename access_traits<T1>::parameter_type t1,
+ typename access_traits<T2>::parameter_type t2,
+ typename access_traits<T3>::parameter_type t3,
+ typename access_traits<T4>::parameter_type t4,
+ typename access_traits<T5>::parameter_type t5,
+ typename access_traits<T6>::parameter_type t6)
+ : inherited(t0, t1, t2, t3, t4, t5, t6, detail::cnull(),
+ detail::cnull(), detail::cnull()) {}
+
+ tuple(typename access_traits<T0>::parameter_type t0,
+ typename access_traits<T1>::parameter_type t1,
+ typename access_traits<T2>::parameter_type t2,
+ typename access_traits<T3>::parameter_type t3,
+ typename access_traits<T4>::parameter_type t4,
+ typename access_traits<T5>::parameter_type t5,
+ typename access_traits<T6>::parameter_type t6,
+ typename access_traits<T7>::parameter_type t7)
+ : inherited(t0, t1, t2, t3, t4, t5, t6, t7, detail::cnull(),
+ detail::cnull()) {}
+
+ tuple(typename access_traits<T0>::parameter_type t0,
+ typename access_traits<T1>::parameter_type t1,
+ typename access_traits<T2>::parameter_type t2,
+ typename access_traits<T3>::parameter_type t3,
+ typename access_traits<T4>::parameter_type t4,
+ typename access_traits<T5>::parameter_type t5,
+ typename access_traits<T6>::parameter_type t6,
+ typename access_traits<T7>::parameter_type t7,
+ typename access_traits<T8>::parameter_type t8)
+ : inherited(t0, t1, t2, t3, t4, t5, t6, t7, t8, detail::cnull()) {}
+
+ tuple(typename access_traits<T0>::parameter_type t0,
+ typename access_traits<T1>::parameter_type t1,
+ typename access_traits<T2>::parameter_type t2,
+ typename access_traits<T3>::parameter_type t3,
+ typename access_traits<T4>::parameter_type t4,
+ typename access_traits<T5>::parameter_type t5,
+ typename access_traits<T6>::parameter_type t6,
+ typename access_traits<T7>::parameter_type t7,
+ typename access_traits<T8>::parameter_type t8,
+ typename access_traits<T9>::parameter_type t9)
+ : inherited(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) {}
+
+
+ template<class U1, class U2>
+ tuple(const cons<U1, U2>& p) : inherited(p) {}
+
+ template <class U1, class U2>
+ tuple& operator=(const cons<U1, U2>& k) {
+ inherited::operator=(k);
+ return *this;
+ }
+
+ template <class U1, class U2>
+ tuple& operator=(const std::pair<U1, U2>& k) {
+ BOOST_STATIC_ASSERT(length<tuple>::value == 2);// check_length = 2
+ this->head = k.first;
+ this->tail.head = k.second;
+ return *this;
+ }
+
+};
+
+// The empty tuple
+template <>
+class tuple<null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type> :
+ public null_type
+{
+public:
+ typedef null_type inherited;
+};
+
+
+// Swallows any assignment (by Doug Gregor)
+namespace detail {
+
+struct swallow_assign;
+typedef void (detail::swallow_assign::*ignore_t)();
+struct swallow_assign {
+ swallow_assign(ignore_t(*)(ignore_t)) {}
+ template<typename T>
+ swallow_assign const& operator=(const T&) const {
+ return *this;
+ }
+};
+
+
+} // namespace detail
+
+// "ignore" allows tuple positions to be ignored when using "tie".
+inline detail::ignore_t ignore(detail::ignore_t) { return 0; }
+
+// ---------------------------------------------------------------------------
+// The call_traits for make_tuple
+// Honours the reference_wrapper class.
+
+// Must be instantiated with plain or const plain types (not with references)
+
+// from template<class T> foo(const T& t) : make_tuple_traits<const T>::type
+// from template<class T> foo(T& t) : make_tuple_traits<T>::type
+
+// Conversions:
+// T -> T,
+// references -> compile_time_error
+// reference_wrapper<T> -> T&
+// const reference_wrapper<T> -> T&
+// array -> const ref array
+
+
+template<class T>
+struct make_tuple_traits {
+ typedef T type;
+
+ // commented away, see below (JJ)
+ // typedef typename IF<
+ // boost::is_function<T>::value,
+ // T&,
+ // T>::RET type;
+
+};
+
+// The is_function test was there originally for plain function types,
+// which can't be stored as such (we must either store them as references or
+// pointers). Such a type could be formed if make_tuple was called with a
+// reference to a function.
+// But this would mean that a const qualified function type was formed in
+// the make_tuple function and hence make_tuple can't take a function
+// reference as a parameter, and thus T can't be a function type.
+// So is_function test was removed.
+// (14.8.3. says that type deduction fails if a cv-qualified function type
+// is created. (It only applies for the case of explicitly specifying template
+// args, though?)) (JJ)
+
+template<class T>
+struct make_tuple_traits<T&> {
+ typedef typename
+ detail::generate_error<T&>::
+ do_not_use_with_reference_type error;
+};
+
+// Arrays can't be stored as plain types; convert them to references.
+// All arrays are converted to const. This is because make_tuple takes its
+// parameters as const T& and thus the knowledge of the potential
+// non-constness of actual argument is lost.
+template<class T, int n> struct make_tuple_traits <T[n]> {
+ typedef const T (&type)[n];
+};
+
+template<class T, int n>
+struct make_tuple_traits<const T[n]> {
+ typedef const T (&type)[n];
+};
+
+template<class T, int n> struct make_tuple_traits<volatile T[n]> {
+ typedef const volatile T (&type)[n];
+};
+
+template<class T, int n>
+struct make_tuple_traits<const volatile T[n]> {
+ typedef const volatile T (&type)[n];
+};
+
+template<class T>
+struct make_tuple_traits<reference_wrapper<T> >{
+ typedef T& type;
+};
+
+template<class T>
+struct make_tuple_traits<const reference_wrapper<T> >{
+ typedef T& type;
+};
+
+template<>
+struct make_tuple_traits<detail::ignore_t(detail::ignore_t)> {
+ typedef detail::swallow_assign type;
+};
+
+
+
+namespace detail {
+
+// a helper traits to make the make_tuple functions shorter (Vesa Karvonen's
+// suggestion)
+template <
+ class T0 = null_type, class T1 = null_type, class T2 = null_type,
+ class T3 = null_type, class T4 = null_type, class T5 = null_type,
+ class T6 = null_type, class T7 = null_type, class T8 = null_type,
+ class T9 = null_type
+>
+struct make_tuple_mapper {
+ typedef
+ tuple<typename make_tuple_traits<T0>::type,
+ typename make_tuple_traits<T1>::type,
+ typename make_tuple_traits<T2>::type,
+ typename make_tuple_traits<T3>::type,
+ typename make_tuple_traits<T4>::type,
+ typename make_tuple_traits<T5>::type,
+ typename make_tuple_traits<T6>::type,
+ typename make_tuple_traits<T7>::type,
+ typename make_tuple_traits<T8>::type,
+ typename make_tuple_traits<T9>::type> type;
+};
+
+} // end detail
+
+// -make_tuple function templates -----------------------------------
+inline tuple<> make_tuple() {
+ return tuple<>();
+}
+
+template<class T0>
+inline typename detail::make_tuple_mapper<T0>::type
+make_tuple(const T0& t0) {
+ typedef typename detail::make_tuple_mapper<T0>::type t;
+ return t(t0);
+}
+
+template<class T0, class T1>
+inline typename detail::make_tuple_mapper<T0, T1>::type
+make_tuple(const T0& t0, const T1& t1) {
+ typedef typename detail::make_tuple_mapper<T0, T1>::type t;
+ return t(t0, t1);
+}
+
+template<class T0, class T1, class T2>
+inline typename detail::make_tuple_mapper<T0, T1, T2>::type
+make_tuple(const T0& t0, const T1& t1, const T2& t2) {
+ typedef typename detail::make_tuple_mapper<T0, T1, T2>::type t;
+ return t(t0, t1, t2);
+}
+
+template<class T0, class T1, class T2, class T3>
+inline typename detail::make_tuple_mapper<T0, T1, T2, T3>::type
+make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3) {
+ typedef typename detail::make_tuple_mapper<T0, T1, T2, T3>::type t;
+ return t(t0, t1, t2, t3);
+}
+
+template<class T0, class T1, class T2, class T3, class T4>
+inline typename detail::make_tuple_mapper<T0, T1, T2, T3, T4>::type
+make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
+ const T4& t4) {
+ typedef typename detail::make_tuple_mapper<T0, T1, T2, T3, T4>::type t;
+ return t(t0, t1, t2, t3, t4);
+}
+
+template<class T0, class T1, class T2, class T3, class T4, class T5>
+inline typename detail::make_tuple_mapper<T0, T1, T2, T3, T4, T5>::type
+make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
+ const T4& t4, const T5& t5) {
+ typedef typename detail::make_tuple_mapper<T0, T1, T2, T3, T4, T5>::type t;
+ return t(t0, t1, t2, t3, t4, t5);
+}
+
+template<class T0, class T1, class T2, class T3, class T4, class T5, class T6>
+inline typename detail::make_tuple_mapper<T0, T1, T2, T3, T4, T5, T6>::type
+make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
+ const T4& t4, const T5& t5, const T6& t6) {
+ typedef typename detail::make_tuple_mapper
+ <T0, T1, T2, T3, T4, T5, T6>::type t;
+ return t(t0, t1, t2, t3, t4, t5, t6);
+}
+
+template<class T0, class T1, class T2, class T3, class T4, class T5, class T6,
+ class T7>
+inline typename detail::make_tuple_mapper<T0, T1, T2, T3, T4, T5, T6, T7>::type
+make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
+ const T4& t4, const T5& t5, const T6& t6, const T7& t7) {
+ typedef typename detail::make_tuple_mapper
+ <T0, T1, T2, T3, T4, T5, T6, T7>::type t;
+ return t(t0, t1, t2, t3, t4, t5, t6, t7);
+}
+
+template<class T0, class T1, class T2, class T3, class T4, class T5, class T6,
+ class T7, class T8>
+inline typename detail::make_tuple_mapper
+ <T0, T1, T2, T3, T4, T5, T6, T7, T8>::type
+make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
+ const T4& t4, const T5& t5, const T6& t6, const T7& t7,
+ const T8& t8) {
+ typedef typename detail::make_tuple_mapper
+ <T0, T1, T2, T3, T4, T5, T6, T7, T8>::type t;
+ return t(t0, t1, t2, t3, t4, t5, t6, t7, t8);
+}
+
+template<class T0, class T1, class T2, class T3, class T4, class T5, class T6,
+ class T7, class T8, class T9>
+inline typename detail::make_tuple_mapper
+ <T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type
+make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
+ const T4& t4, const T5& t5, const T6& t6, const T7& t7,
+ const T8& t8, const T9& t9) {
+ typedef typename detail::make_tuple_mapper
+ <T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type t;
+ return t(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9);
+}
+
+namespace detail {
+
+template<class T>
+struct tie_traits {
+ typedef T& type;
+};
+
+template<>
+struct tie_traits<ignore_t(ignore_t)> {
+ typedef swallow_assign type;
+};
+
+template<>
+struct tie_traits<void> {
+ typedef null_type type;
+};
+
+template <
+ class T0 = void, class T1 = void, class T2 = void,
+ class T3 = void, class T4 = void, class T5 = void,
+ class T6 = void, class T7 = void, class T8 = void,
+ class T9 = void
+>
+struct tie_mapper {
+ typedef
+ tuple<typename tie_traits<T0>::type,
+ typename tie_traits<T1>::type,
+ typename tie_traits<T2>::type,
+ typename tie_traits<T3>::type,
+ typename tie_traits<T4>::type,
+ typename tie_traits<T5>::type,
+ typename tie_traits<T6>::type,
+ typename tie_traits<T7>::type,
+ typename tie_traits<T8>::type,
+ typename tie_traits<T9>::type> type;
+};
+
+}
+
+// Tie function templates -------------------------------------------------
+template<class T0>
+inline typename detail::tie_mapper<T0>::type
+tie(T0& t0) {
+ typedef typename detail::tie_mapper<T0>::type t;
+ return t(t0);
+}
+
+template<class T0, class T1>
+inline typename detail::tie_mapper<T0, T1>::type
+tie(T0& t0, T1& t1) {
+ typedef typename detail::tie_mapper<T0, T1>::type t;
+ return t(t0, t1);
+}
+
+template<class T0, class T1, class T2>
+inline typename detail::tie_mapper<T0, T1, T2>::type
+tie(T0& t0, T1& t1, T2& t2) {
+ typedef typename detail::tie_mapper<T0, T1, T2>::type t;
+ return t(t0, t1, t2);
+}
+
+template<class T0, class T1, class T2, class T3>
+inline typename detail::tie_mapper<T0, T1, T2, T3>::type
+tie(T0& t0, T1& t1, T2& t2, T3& t3) {
+ typedef typename detail::tie_mapper<T0, T1, T2, T3>::type t;
+ return t(t0, t1, t2, t3);
+}
+
+template<class T0, class T1, class T2, class T3, class T4>
+inline typename detail::tie_mapper<T0, T1, T2, T3, T4>::type
+tie(T0& t0, T1& t1, T2& t2, T3& t3,
+ T4& t4) {
+ typedef typename detail::tie_mapper<T0, T1, T2, T3, T4>::type t;
+ return t(t0, t1, t2, t3, t4);
+}
+
+template<class T0, class T1, class T2, class T3, class T4, class T5>
+inline typename detail::tie_mapper<T0, T1, T2, T3, T4, T5>::type
+tie(T0& t0, T1& t1, T2& t2, T3& t3,
+ T4& t4, T5& t5) {
+ typedef typename detail::tie_mapper<T0, T1, T2, T3, T4, T5>::type t;
+ return t(t0, t1, t2, t3, t4, t5);
+}
+
+template<class T0, class T1, class T2, class T3, class T4, class T5, class T6>
+inline typename detail::tie_mapper<T0, T1, T2, T3, T4, T5, T6>::type
+tie(T0& t0, T1& t1, T2& t2, T3& t3,
+ T4& t4, T5& t5, T6& t6) {
+ typedef typename detail::tie_mapper
+ <T0, T1, T2, T3, T4, T5, T6>::type t;
+ return t(t0, t1, t2, t3, t4, t5, t6);
+}
+
+template<class T0, class T1, class T2, class T3, class T4, class T5, class T6,
+ class T7>
+inline typename detail::tie_mapper<T0, T1, T2, T3, T4, T5, T6, T7>::type
+tie(T0& t0, T1& t1, T2& t2, T3& t3,
+ T4& t4, T5& t5, T6& t6, T7& t7) {
+ typedef typename detail::tie_mapper
+ <T0, T1, T2, T3, T4, T5, T6, T7>::type t;
+ return t(t0, t1, t2, t3, t4, t5, t6, t7);
+}
+
+template<class T0, class T1, class T2, class T3, class T4, class T5, class T6,
+ class T7, class T8>
+inline typename detail::tie_mapper
+ <T0, T1, T2, T3, T4, T5, T6, T7, T8>::type
+tie(T0& t0, T1& t1, T2& t2, T3& t3,
+ T4& t4, T5& t5, T6& t6, T7& t7,
+ T8& t8) {
+ typedef typename detail::tie_mapper
+ <T0, T1, T2, T3, T4, T5, T6, T7, T8>::type t;
+ return t(t0, t1, t2, t3, t4, t5, t6, t7, t8);
+}
+
+template<class T0, class T1, class T2, class T3, class T4, class T5, class T6,
+ class T7, class T8, class T9>
+inline typename detail::tie_mapper
+ <T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type
+tie(T0& t0, T1& t1, T2& t2, T3& t3,
+ T4& t4, T5& t5, T6& t6, T7& t7,
+ T8& t8, T9& t9) {
+ typedef typename detail::tie_mapper
+ <T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type t;
+ return t(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9);
+}
+
+template <class T0, class T1, class T2, class T3, class T4,
+ class T5, class T6, class T7, class T8, class T9>
+void swap(tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>& lhs,
+ tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>& rhs);
+inline void swap(null_type&, null_type&) {}
+template<class HH>
+inline void swap(cons<HH, null_type>& lhs, cons<HH, null_type>& rhs) {
+ ::boost::swap(lhs.head, rhs.head);
+}
+template<class HH, class TT>
+inline void swap(cons<HH, TT>& lhs, cons<HH, TT>& rhs) {
+ ::boost::swap(lhs.head, rhs.head);
+ ::boost::tuples::swap(lhs.tail, rhs.tail);
+}
+template <class T0, class T1, class T2, class T3, class T4,
+ class T5, class T6, class T7, class T8, class T9>
+inline void swap(tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>& lhs,
+ tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>& rhs) {
+ typedef tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> tuple_type;
+ typedef typename tuple_type::inherited base;
+ ::boost::tuples::swap(static_cast<base&>(lhs), static_cast<base&>(rhs));
+}
+
+} // end of namespace tuples
+} // end of namespace boost
+
+
+#if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
+#pragma GCC diagnostic pop
+#endif
+
+
+#endif // BOOST_TUPLE_BASIC_HPP
diff --git a/include/boost/tuple/tuple.hpp b/include/boost/tuple/tuple.hpp
new file mode 100644
index 0000000..d71e7df
--- /dev/null
+++ b/include/boost/tuple/tuple.hpp
@@ -0,0 +1,67 @@
+// tuple.hpp - Boost Tuple Library --------------------------------------
+
+// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+//
+// 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)
+
+// For more information, see http://www.boost.org
+
+// -----------------------------------------------------------------
+
+#ifndef BOOST_TUPLE_HPP
+#define BOOST_TUPLE_HPP
+
+#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730
+// Work around a compiler bug.
+// boost::python::tuple has to be seen by the compiler before the
+// boost::tuple class template.
+namespace boost { namespace python { class tuple; }}
+#endif
+
+#include <boost/config.hpp>
+#include <boost/static_assert.hpp>
+
+// other compilers
+#include <boost/ref.hpp>
+#include <boost/tuple/detail/tuple_basic.hpp>
+
+
+namespace boost {
+
+using tuples::tuple;
+using tuples::make_tuple;
+using tuples::tie;
+#if !defined(BOOST_NO_USING_TEMPLATE)
+using tuples::get;
+#else
+//
+// The "using tuples::get" statement causes the
+// Borland compiler to ICE, use forwarding
+// functions instead:
+//
+template<int N, class HT, class TT>
+inline typename tuples::access_traits<
+ typename tuples::element<N, tuples::cons<HT, TT> >::type
+ >::non_const_type
+get(tuples::cons<HT, TT>& c) {
+ return tuples::get<N,HT,TT>(c);
+}
+// get function for const cons-lists, returns a const reference to
+// the element. If the element is a reference, returns the reference
+// as such (that is, can return a non-const reference)
+template<int N, class HT, class TT>
+inline typename tuples::access_traits<
+ typename tuples::element<N, tuples::cons<HT, TT> >::type
+ >::const_type
+get(const tuples::cons<HT, TT>& c) {
+ return tuples::get<N,HT,TT>(c);
+}
+
+#endif // BOOST_NO_USING_TEMPLATE
+
+} // end namespace boost
+
+
+#endif // BOOST_TUPLE_HPP
diff --git a/include/boost/tuple/tuple_comparison.hpp b/include/boost/tuple/tuple_comparison.hpp
new file mode 100644
index 0000000..0a61952
--- /dev/null
+++ b/include/boost/tuple/tuple_comparison.hpp
@@ -0,0 +1,175 @@
+// tuple_comparison.hpp -----------------------------------------------------
+//
+// Copyright (C) 2001 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2001 Gary Powell (gary.powell@sierra.com)
+//
+// 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)
+//
+// For more information, see http://www.boost.org
+//
+// (The idea and first impl. of comparison operators was from Doug Gregor)
+
+// -----------------------------------------------------------------
+
+#ifndef BOOST_TUPLE_COMPARISON_HPP
+#define BOOST_TUPLE_COMPARISON_HPP
+
+#include <boost/tuple/tuple.hpp>
+
+// -------------------------------------------------------------
+// equality and comparison operators
+//
+// == and != compare tuples elementwise
+// <, >, <= and >= use lexicographical ordering
+//
+// Any operator between tuples of different length fails at compile time
+// No dependencies between operators are assumed
+// (i.e. !(a<b) does not imply a>=b, a!=b does not imply a==b etc.
+// so any weirdnesses of elementary operators are respected).
+//
+// -------------------------------------------------------------
+
+
+namespace boost {
+namespace tuples {
+
+inline bool operator==(const null_type&, const null_type&) { return true; }
+inline bool operator>=(const null_type&, const null_type&) { return true; }
+inline bool operator<=(const null_type&, const null_type&) { return true; }
+inline bool operator!=(const null_type&, const null_type&) { return false; }
+inline bool operator<(const null_type&, const null_type&) { return false; }
+inline bool operator>(const null_type&, const null_type&) { return false; }
+
+
+namespace detail {
+ // comparison operators check statically the length of its operands and
+ // delegate the comparing task to the following functions. Hence
+ // the static check is only made once (should help the compiler).
+ // These functions assume tuples to be of the same length.
+
+
+template<class T1, class T2>
+inline bool eq(const T1& lhs, const T2& rhs) {
+ return lhs.get_head() == rhs.get_head() &&
+ eq(lhs.get_tail(), rhs.get_tail());
+}
+template<>
+inline bool eq<null_type,null_type>(const null_type&, const null_type&) { return true; }
+
+template<class T1, class T2>
+inline bool neq(const T1& lhs, const T2& rhs) {
+ return lhs.get_head() != rhs.get_head() ||
+ neq(lhs.get_tail(), rhs.get_tail());
+}
+template<>
+inline bool neq<null_type,null_type>(const null_type&, const null_type&) { return false; }
+
+template<class T1, class T2>
+inline bool lt(const T1& lhs, const T2& rhs) {
+ return lhs.get_head() < rhs.get_head() ||
+ ( !(rhs.get_head() < lhs.get_head()) &&
+ lt(lhs.get_tail(), rhs.get_tail()));
+}
+template<>
+inline bool lt<null_type,null_type>(const null_type&, const null_type&) { return false; }
+
+template<class T1, class T2>
+inline bool gt(const T1& lhs, const T2& rhs) {
+ return lhs.get_head() > rhs.get_head() ||
+ ( !(rhs.get_head() > lhs.get_head()) &&
+ gt(lhs.get_tail(), rhs.get_tail()));
+}
+template<>
+inline bool gt<null_type,null_type>(const null_type&, const null_type&) { return false; }
+
+template<class T1, class T2>
+inline bool lte(const T1& lhs, const T2& rhs) {
+ return lhs.get_head() <= rhs.get_head() &&
+ ( !(rhs.get_head() <= lhs.get_head()) ||
+ lte(lhs.get_tail(), rhs.get_tail()));
+}
+template<>
+inline bool lte<null_type,null_type>(const null_type&, const null_type&) { return true; }
+
+template<class T1, class T2>
+inline bool gte(const T1& lhs, const T2& rhs) {
+ return lhs.get_head() >= rhs.get_head() &&
+ ( !(rhs.get_head() >= lhs.get_head()) ||
+ gte(lhs.get_tail(), rhs.get_tail()));
+}
+template<>
+inline bool gte<null_type,null_type>(const null_type&, const null_type&) { return true; }
+
+} // end of namespace detail
+
+
+// equal ----
+
+template<class T1, class T2, class S1, class S2>
+inline bool operator==(const cons<T1, T2>& lhs, const cons<S1, S2>& rhs)
+{
+ // check that tuple lengths are equal
+ BOOST_STATIC_ASSERT(length<T2>::value == length<S2>::value);
+
+ return detail::eq(lhs, rhs);
+}
+
+// not equal -----
+
+template<class T1, class T2, class S1, class S2>
+inline bool operator!=(const cons<T1, T2>& lhs, const cons<S1, S2>& rhs)
+{
+
+ // check that tuple lengths are equal
+ BOOST_STATIC_ASSERT(length<T2>::value == length<S2>::value);
+
+ return detail::neq(lhs, rhs);
+}
+
+// <
+template<class T1, class T2, class S1, class S2>
+inline bool operator<(const cons<T1, T2>& lhs, const cons<S1, S2>& rhs)
+{
+ // check that tuple lengths are equal
+ BOOST_STATIC_ASSERT(length<T2>::value == length<S2>::value);
+
+ return detail::lt(lhs, rhs);
+}
+
+// >
+template<class T1, class T2, class S1, class S2>
+inline bool operator>(const cons<T1, T2>& lhs, const cons<S1, S2>& rhs)
+{
+ // check that tuple lengths are equal
+ BOOST_STATIC_ASSERT(length<T2>::value == length<S2>::value);
+
+ return detail::gt(lhs, rhs);
+}
+
+// <=
+template<class T1, class T2, class S1, class S2>
+inline bool operator<=(const cons<T1, T2>& lhs, const cons<S1, S2>& rhs)
+{
+ // check that tuple lengths are equal
+ BOOST_STATIC_ASSERT(length<T2>::value == length<S2>::value);
+
+ return detail::lte(lhs, rhs);
+}
+
+// >=
+template<class T1, class T2, class S1, class S2>
+inline bool operator>=(const cons<T1, T2>& lhs, const cons<S1, S2>& rhs)
+{
+ // check that tuple lengths are equal
+ BOOST_STATIC_ASSERT(length<T2>::value == length<S2>::value);
+
+ return detail::gte(lhs, rhs);
+}
+
+} // end of namespace tuples
+} // end of namespace boost
+
+
+#endif // BOOST_TUPLE_COMPARISON_HPP
diff --git a/include/boost/tuple/tuple_io.hpp b/include/boost/tuple/tuple_io.hpp
new file mode 100644
index 0000000..f21c7ed
--- /dev/null
+++ b/include/boost/tuple/tuple_io.hpp
@@ -0,0 +1,339 @@
+// tuple_io.hpp --------------------------------------------------------------
+
+// Copyright (C) 2001 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// 2001 Gary Powell (gary.powell@sierra.com)
+//
+// 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)
+// For more information, see http://www.boost.org
+
+// ----------------------------------------------------------------------------
+
+#ifndef BOOST_TUPLE_IO_HPP
+#define BOOST_TUPLE_IO_HPP
+
+#include <istream>
+#include <ostream>
+
+#include <sstream>
+
+#include <boost/tuple/tuple.hpp>
+
+// This is ugly: one should be using twoargument isspace since whitspace can
+// be locale dependent, in theory at least.
+// not all libraries implement have the two-arg version, so we need to
+// use the one-arg one, which one should get with <cctype> but there seem
+// to be exceptions to this.
+
+#if !defined (BOOST_NO_STD_LOCALE)
+
+#include <locale> // for two-arg isspace
+
+#else
+
+#include <cctype> // for one-arg (old) isspace
+#include <ctype.h> // Metrowerks does not find one-arg isspace from cctype
+
+#endif
+
+namespace boost {
+namespace tuples {
+
+namespace detail {
+
+class format_info {
+public:
+
+ enum manipulator_type { open, close, delimiter };
+ BOOST_STATIC_CONSTANT(int, number_of_manipulators = delimiter + 1);
+private:
+
+ static int get_stream_index (int m)
+ {
+ static const int stream_index[number_of_manipulators]
+ = { std::ios::xalloc(), std::ios::xalloc(), std::ios::xalloc() };
+
+ return stream_index[m];
+ }
+
+ format_info(const format_info&);
+ format_info();
+
+
+public:
+
+ template<class CharType, class CharTrait>
+ static CharType get_manipulator(std::basic_ios<CharType, CharTrait>& i,
+ manipulator_type m) {
+ // The manipulators are stored as long.
+ // A valid instanitation of basic_stream allows CharType to be any POD,
+ // hence, the static_cast may fail (it fails if long is not convertible
+ // to CharType
+ CharType c = static_cast<CharType>(i.iword(get_stream_index(m)) );
+ // parentheses and space are the default manipulators
+ if (!c) {
+ switch(m) {
+ case detail::format_info::open : c = i.widen('('); break;
+ case detail::format_info::close : c = i.widen(')'); break;
+ case detail::format_info::delimiter : c = i.widen(' '); break;
+ }
+ }
+ return c;
+ }
+
+
+ template<class CharType, class CharTrait>
+ static void set_manipulator(std::basic_ios<CharType, CharTrait>& i,
+ manipulator_type m, CharType c) {
+ // The manipulators are stored as long.
+ // A valid instanitation of basic_stream allows CharType to be any POD,
+ // hence, the static_cast may fail (it fails if CharType is not
+ // convertible long.
+ i.iword(get_stream_index(m)) = static_cast<long>(c);
+ }
+};
+
+} // end of namespace detail
+
+template<class CharType>
+class tuple_manipulator {
+ const detail::format_info::manipulator_type mt;
+ CharType f_c;
+public:
+ explicit tuple_manipulator(detail::format_info::manipulator_type m,
+ const char c = 0)
+ : mt(m), f_c(c) {}
+
+ template<class CharTrait>
+ void set(std::basic_ios<CharType, CharTrait> &io) const {
+ detail::format_info::set_manipulator(io, mt, f_c);
+ }
+};
+
+
+template<class CharType, class CharTrait>
+inline std::basic_ostream<CharType, CharTrait>&
+operator<<(std::basic_ostream<CharType, CharTrait>& o, const tuple_manipulator<CharType>& m) {
+ m.set(o);
+ return o;
+}
+
+template<class CharType, class CharTrait>
+inline std::basic_istream<CharType, CharTrait>&
+operator>>(std::basic_istream<CharType, CharTrait>& i, const tuple_manipulator<CharType>& m) {
+ m.set(i);
+ return i;
+}
+
+
+template<class CharType>
+inline tuple_manipulator<CharType> set_open(const CharType c) {
+ return tuple_manipulator<CharType>(detail::format_info::open, c);
+}
+
+template<class CharType>
+inline tuple_manipulator<CharType> set_close(const CharType c) {
+ return tuple_manipulator<CharType>(detail::format_info::close, c);
+}
+
+template<class CharType>
+inline tuple_manipulator<CharType> set_delimiter(const CharType c) {
+ return tuple_manipulator<CharType>(detail::format_info::delimiter, c);
+}
+
+
+
+
+
+// -------------------------------------------------------------
+// printing tuples to ostream in format (a b c)
+// parentheses and space are defaults, but can be overriden with manipulators
+// set_open, set_close and set_delimiter
+
+namespace detail {
+
+// Note: The order of the print functions is critical
+// to let a conforming compiler find and select the correct one.
+
+
+template<class CharType, class CharTrait, class T1>
+inline std::basic_ostream<CharType, CharTrait>&
+print(std::basic_ostream<CharType, CharTrait>& o, const cons<T1, null_type>& t) {
+ return o << t.head;
+}
+
+
+template<class CharType, class CharTrait>
+inline std::basic_ostream<CharType, CharTrait>&
+print(std::basic_ostream<CharType, CharTrait>& o, const null_type&) {
+ return o;
+}
+
+template<class CharType, class CharTrait, class T1, class T2>
+inline std::basic_ostream<CharType, CharTrait>&
+print(std::basic_ostream<CharType, CharTrait>& o, const cons<T1, T2>& t) {
+
+ const CharType d = format_info::get_manipulator(o, format_info::delimiter);
+
+ o << t.head;
+
+ o << d;
+
+ return print(o, t.tail);
+}
+
+template<class CharT, class Traits, class T>
+inline bool handle_width(std::basic_ostream<CharT, Traits>& o, const T& t) {
+ std::streamsize width = o.width();
+ if(width == 0) return false;
+
+ std::basic_ostringstream<CharT, Traits> ss;
+
+ ss.copyfmt(o);
+ ss.tie(0);
+ ss.width(0);
+
+ ss << t;
+ o << ss.str();
+
+ return true;
+}
+
+
+} // namespace detail
+
+
+template<class CharType, class CharTrait>
+inline std::basic_ostream<CharType, CharTrait>&
+operator<<(std::basic_ostream<CharType, CharTrait>& o,
+ const null_type& t) {
+ if (!o.good() ) return o;
+ if (detail::handle_width(o, t)) return o;
+
+ const CharType l =
+ detail::format_info::get_manipulator(o, detail::format_info::open);
+ const CharType r =
+ detail::format_info::get_manipulator(o, detail::format_info::close);
+
+ o << l;
+ o << r;
+
+ return o;
+}
+
+template<class CharType, class CharTrait, class T1, class T2>
+inline std::basic_ostream<CharType, CharTrait>&
+operator<<(std::basic_ostream<CharType, CharTrait>& o,
+ const cons<T1, T2>& t) {
+ if (!o.good() ) return o;
+ if (detail::handle_width(o, t)) return o;
+
+ const CharType l =
+ detail::format_info::get_manipulator(o, detail::format_info::open);
+ const CharType r =
+ detail::format_info::get_manipulator(o, detail::format_info::close);
+
+ o << l;
+
+ detail::print(o, t);
+
+ o << r;
+
+ return o;
+}
+
+
+// -------------------------------------------------------------
+// input stream operators
+
+namespace detail {
+
+
+template<class CharType, class CharTrait>
+inline std::basic_istream<CharType, CharTrait>&
+extract_and_check_delimiter(
+ std::basic_istream<CharType, CharTrait> &is, format_info::manipulator_type del)
+{
+ const CharType d = format_info::get_manipulator(is, del);
+
+#if defined (BOOST_NO_STD_LOCALE)
+ const bool is_delimiter = !isspace(d);
+#elif defined ( __BORLANDC__ )
+ const bool is_delimiter = !std::use_facet< std::ctype< CharType > >
+ (is.getloc() ).is( std::ctype_base::space, d);
+#else
+ const bool is_delimiter = (!std::isspace(d, is.getloc()) );
+#endif
+
+ CharType c;
+ if (is_delimiter) {
+ is >> c;
+ if (is.good() && c!=d) {
+ is.setstate(std::ios::failbit);
+ }
+ } else {
+ is >> std::ws;
+ }
+ return is;
+}
+
+
+template<class CharType, class CharTrait, class T1>
+inline std::basic_istream<CharType, CharTrait> &
+read (std::basic_istream<CharType, CharTrait> &is, cons<T1, null_type>& t1) {
+
+ if (!is.good()) return is;
+
+ return is >> t1.head;
+}
+
+template<class CharType, class CharTrait, class T1, class T2>
+inline std::basic_istream<CharType, CharTrait>&
+read(std::basic_istream<CharType, CharTrait> &is, cons<T1, T2>& t1) {
+
+ if (!is.good()) return is;
+
+ is >> t1.head;
+
+
+ extract_and_check_delimiter(is, format_info::delimiter);
+
+ return read(is, t1.tail);
+}
+
+} // end namespace detail
+
+
+template<class CharType, class CharTrait>
+inline std::basic_istream<CharType, CharTrait>&
+operator>>(std::basic_istream<CharType, CharTrait> &is, null_type&) {
+
+ if (!is.good() ) return is;
+
+ detail::extract_and_check_delimiter(is, detail::format_info::open);
+ detail::extract_and_check_delimiter(is, detail::format_info::close);
+
+ return is;
+}
+
+template<class CharType, class CharTrait, class T1, class T2>
+inline std::basic_istream<CharType, CharTrait>&
+operator>>(std::basic_istream<CharType, CharTrait>& is, cons<T1, T2>& t1) {
+
+ if (!is.good() ) return is;
+
+ detail::extract_and_check_delimiter(is, detail::format_info::open);
+
+ detail::read(is, t1);
+
+ detail::extract_and_check_delimiter(is, detail::format_info::close);
+
+ return is;
+}
+
+
+} // end of namespace tuples
+} // end of namespace boost
+
+#endif // BOOST_TUPLE_IO_HPP
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..437c1e7
--- /dev/null
+++ b/index.html
@@ -0,0 +1,13 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0; URL=doc/html/tuple_users_guide.html">
+</head>
+<body>
+Automatic redirection failed, please go to <a href="doc/html/tuple_users_guide.html">doc/html/tuple_users_guide.html</a>
+ <hr>
+<p>© Copyright Beman Dawes, 2001</p>
+<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
+file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
+at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
+</body>
+</html>
diff --git a/meta/libraries.json b/meta/libraries.json
new file mode 100644
index 0000000..0d49822
--- /dev/null
+++ b/meta/libraries.json
@@ -0,0 +1,17 @@
+{
+ "key": "tuple",
+ "name": "Tuple",
+ "authors": [
+ "Jaakko Järvi"
+ ],
+ "description": "Ease definition of functions returning multiple values, and more.",
+ "std": [
+ "tr1"
+ ],
+ "category": [
+ "Data"
+ ],
+ "maintainers": [
+ "Jaakko Jarvi <jarvi -at- cs.tamu.edu>"
+ ]
+}
diff --git a/test/Jamfile b/test/Jamfile
new file mode 100644
index 0000000..66574f6
--- /dev/null
+++ b/test/Jamfile
@@ -0,0 +1,8 @@
+
+project : requirements <library>/boost/test//boost_test_exec_monitor ;
+
+test-suite tuple :
+ [ run tuple_test_bench.cpp ]
+ [ run io_test.cpp ]
+ [ run another_tuple_test_bench.cpp ]
+ ;
\ No newline at end of file
diff --git a/test/README b/test/README
new file mode 100644
index 0000000..6047c49
--- /dev/null
+++ b/test/README
@@ -0,0 +1,16 @@
+To compile the
+
+libs/tuple/test/*.cpp
+
+files, you need to set include paths
+for boost.
+For example, in libs/tuple/test directory you would type (using g++):
+
+g++ -I../../.. tuple_test_bench.cpp
+
+The following is not true anymore:
+
+ If you want to use tuple_io, you need to compile and link src/tuple.cpp:
+ g++ -I../../.. ../src/tuple.cpp io_test.cpp
+
+Thanks to Hartmut Kaiser's suggestion, the tuple.cpp is not needed anymore.
diff --git a/test/another_tuple_test_bench.cpp b/test/another_tuple_test_bench.cpp
new file mode 100644
index 0000000..15074da
--- /dev/null
+++ b/test/another_tuple_test_bench.cpp
@@ -0,0 +1,163 @@
+// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+//
+// 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)
+
+// For more information, see http://www.boost.org
+
+
+// another_test_bench.cpp --------------------------------
+
+// This file has various tests to see that things that shouldn't
+// compile, don't compile.
+
+// Defining any of E1 to E5 or E7 to E11 opens some illegal code that
+// should cause the compliation to fail.
+
+#define BOOST_INCLUDE_MAIN // for testing, include rather than link
+#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
+
+#include "boost/tuple/tuple.hpp"
+
+#include <string>
+#include <utility>
+
+using namespace boost;
+using namespace boost::tuples;
+
+
+template<class T> void dummy(const T&) {}
+
+class A {}; class B {}; class C {};
+
+// A non-copyable class
+class no_copy {
+ no_copy(const no_copy&) {}
+public:
+ no_copy() {};
+};
+
+no_copy y;
+
+#ifdef E1
+tuple<no_copy> v1; // should faild
+#endif
+
+
+#ifdef E2
+char cs[10];
+tuple<char[10]> v3; // should fail, arrays must be stored as references
+#endif
+
+// a class without a public default constructor
+class no_def_constructor {
+ no_def_constructor() {}
+public:
+ no_def_constructor(std::string) {} // can be constructed with a string
+};
+
+void foo1() {
+
+#ifdef E3
+ dummy(tuple<no_def_constructor, no_def_constructor, no_def_constructor>());
+ // should fail
+
+#endif
+}
+
+void foo2() {
+// testing default values
+#ifdef E4
+ dummy(tuple<double&>()); // should fail, not defaults for references
+ dummy(tuple<const double&>()); // likewise
+#endif
+
+#ifdef E5
+ double dd = 5;
+ dummy(tuple<double&>(dd+3.14)); // should fail, temporary to non-const reference
+#endif
+}
+
+
+
+// make_tuple ------------------------------------------
+
+
+ void foo3() {
+#ifdef E7
+ std::make_pair("Doesn't","Work"); // fails
+#endif
+ // make_tuple("Does", "Work"); // this should work
+}
+
+
+
+// - testing element access
+
+void foo4()
+{
+ double d = 2.7;
+ A a;
+ tuple<int, double&, const A&> t(1, d, a);
+ const tuple<int, double&, const A> ct = t;
+ (void)ct;
+#ifdef E8
+ get<0>(ct) = 5; // can't assign to const
+#endif
+
+#ifdef E9
+ get<4>(t) = A(); // can't assign to const
+#endif
+#ifdef E10
+ dummy(get<5>(ct)); // illegal index
+#endif
+}
+
+// testing copy and assignment with implicit conversions between elements
+// testing tie
+
+ class AA {};
+ class BB : public AA {};
+ struct CC { CC() {} CC(const BB& b) {} };
+ struct DD { operator CC() const { return CC(); }; };
+
+ void foo5() {
+ tuple<char, BB*, BB, DD> t;
+ (void)t;
+ tuple<char, char> aaa;
+ tuple<int, int> bbb(aaa);
+ (void)bbb;
+ // tuple<int, AA*, CC, CC> a = t;
+ // a = t;
+ }
+
+
+// testing tie
+// testing assignment from std::pair
+void foo7() {
+
+ tuple<int, int, float> a;
+#ifdef E11
+ a = std::make_pair(1, 2); // should fail, tuple is of length 3, not 2
+#endif
+
+ dummy(a);
+}
+
+
+
+// --------------------------------
+// ----------------------------
+int test_main(int, char *[]) {
+
+ foo1();
+ foo2();
+ foo3();
+ foo4();
+ foo5();
+
+ foo7();
+
+ return 0;
+}
diff --git a/test/io_test.cpp b/test/io_test.cpp
new file mode 100644
index 0000000..382f8cc
--- /dev/null
+++ b/test/io_test.cpp
@@ -0,0 +1,143 @@
+// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+//
+// 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)
+
+// For more information, see http://www.boost.org
+
+// -- io_test.cpp -----------------------------------------------
+//
+// Testing the I/O facilities of tuples
+
+#define BOOST_INCLUDE_MAIN // for testing, include rather than link
+#include "boost/test/test_tools.hpp" // see "Header Implementation Option"
+
+#include "boost/tuple/tuple_io.hpp"
+#include "boost/tuple/tuple_comparison.hpp"
+
+#include <fstream>
+#include <iterator>
+#include <algorithm>
+#include <string>
+#include <iomanip>
+
+#if defined BOOST_NO_STRINGSTREAM
+#include <strstream>
+#else
+#include <sstream>
+#endif
+
+using namespace boost;
+
+#if defined BOOST_NO_STRINGSTREAM
+typedef std::ostrstream useThisOStringStream;
+typedef std::istrstream useThisIStringStream;
+#else
+typedef std::ostringstream useThisOStringStream;
+typedef std::istringstream useThisIStringStream;
+#endif
+
+int test_main(int argc, char * argv[] ) {
+ (void)argc;
+ (void)argv;
+ using boost::tuples::set_close;
+ using boost::tuples::set_open;
+ using boost::tuples::set_delimiter;
+
+ useThisOStringStream os1;
+
+ // Set format [a, b, c] for os1
+ os1 << set_open('[');
+ os1 << set_close(']');
+ os1 << set_delimiter(',');
+ os1 << make_tuple(1, 2, 3);
+ BOOST_CHECK (os1.str() == std::string("[1,2,3]") );
+
+ {
+ useThisOStringStream os2;
+ // Set format (a:b:c) for os2;
+ os2 << set_open('(');
+ os2 << set_close(')');
+ os2 << set_delimiter(':');
+#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+ os2 << make_tuple("TUPU", "HUPU", "LUPU", 4.5);
+ BOOST_CHECK (os2.str() == std::string("(TUPU:HUPU:LUPU:4.5)") );
+#endif
+ }
+
+ // The format is still [a, b, c] for os1
+ os1 << make_tuple(1, 2, 3);
+ BOOST_CHECK (os1.str() == std::string("[1,2,3][1,2,3]") );
+
+ // check empty tuple.
+ useThisOStringStream os3;
+ os3 << make_tuple();
+ BOOST_CHECK (os3.str() == std::string("()") );
+ os3 << set_open('[');
+ os3 << set_close(']');
+ os3 << make_tuple();
+ BOOST_CHECK (os3.str() == std::string("()[]") );
+
+ // check width
+ useThisOStringStream os4;
+ os4 << std::setw(10) << make_tuple(1, 2, 3);
+ BOOST_CHECK (os4.str() == std::string(" (1 2 3)") );
+
+ std::ofstream tmp("temp.tmp");
+
+#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+ tmp << make_tuple("One", "Two", 3);
+#endif
+ tmp << set_delimiter(':');
+ tmp << make_tuple(1000, 2000, 3000) << std::endl;
+
+ tmp.close();
+
+ // When teading tuples from a stream, manipulators must be set correctly:
+ std::ifstream tmp3("temp.tmp");
+ tuple<std::string, std::string, int> j;
+
+#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+ tmp3 >> j;
+ BOOST_CHECK (tmp3.good() );
+#endif
+
+ tmp3 >> set_delimiter(':');
+ tuple<int, int, int> i;
+ tmp3 >> i;
+ BOOST_CHECK (tmp3.good() );
+
+ tmp3.close();
+
+
+ // reading tuple<int, int, int> in format (a b c);
+ useThisIStringStream is1("(100 200 300)");
+
+ tuple<int, int, int> ti1;
+ BOOST_CHECK(bool(is1 >> ti1));
+ BOOST_CHECK(ti1 == make_tuple(100, 200, 300));
+
+ useThisIStringStream is2("()");
+ tuple<> ti2;
+ BOOST_CHECK(bool(is2 >> ti2));
+ useThisIStringStream is3("[]");
+ is3 >> set_open('[');
+ is3 >> set_close(']');
+ BOOST_CHECK(bool(is3 >> ti2));
+
+ // Make sure that whitespace between elements
+ // is skipped.
+ useThisIStringStream is4("(100 200 300)");
+
+ BOOST_CHECK(bool(is4 >> std::noskipws >> ti1));
+ BOOST_CHECK(ti1 == make_tuple(100, 200, 300));
+
+ // Note that strings are problematic:
+ // writing a tuple on a stream and reading it back doesn't work in
+ // general. If this is wanted, some kind of a parseable string class
+ // should be used.
+
+ return 0;
+}
+
diff --git a/test/tuple_test_bench.cpp b/test/tuple_test_bench.cpp
new file mode 100644
index 0000000..8bf756f
--- /dev/null
+++ b/test/tuple_test_bench.cpp
@@ -0,0 +1,497 @@
+// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+//
+// 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)
+
+// For more information, see http://www.boost.org
+
+// tuple_test_bench.cpp --------------------------------
+
+#define BOOST_INCLUDE_MAIN // for testing, include rather than link
+#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
+
+#include "boost/tuple/tuple.hpp"
+
+#include "boost/tuple/tuple_comparison.hpp"
+
+#include "boost/type_traits/is_const.hpp"
+
+#include "boost/ref.hpp"
+#include <string>
+#include <utility>
+
+using namespace boost;
+
+// ----------------------------------------------------------------------------
+// helpers
+// ----------------------------------------------------------------------------
+
+class A {};
+class B {};
+class C {};
+
+// classes with different kinds of conversions
+class AA {};
+class BB : public AA {};
+struct CC { CC() {} CC(const BB&) {} };
+struct DD { operator CC() const { return CC(); }; };
+
+// something to prevent warnings for unused variables
+template<class T> void dummy(const T&) {}
+
+// no public default constructor
+class foo {
+public:
+ explicit foo(int v) : val(v) {}
+
+ bool operator==(const foo& other) const {
+ return val == other.val;
+ }
+
+private:
+ foo() {}
+ int val;
+};
+
+// another class without a public default constructor
+class no_def_constructor {
+ no_def_constructor() {}
+public:
+ no_def_constructor(std::string) {}
+};
+
+// A non-copyable class
+class no_copy {
+ no_copy(const no_copy&) {}
+public:
+ no_copy() {};
+};
+
+
+// ----------------------------------------------------------------------------
+// Testing different element types --------------------------------------------
+// ----------------------------------------------------------------------------
+
+
+typedef tuple<int> t1;
+
+typedef tuple<double&, const double&, const double, double*, const double*> t2;
+typedef tuple<A, int(*)(char, int), C> t3;
+typedef tuple<std::string, std::pair<A, B> > t4;
+typedef tuple<A*, tuple<const A*, const B&, C>, bool, void*> t5;
+typedef tuple<volatile int, const volatile char&, int(&)(float) > t6;
+
+# if !defined(__BORLANDC__) || __BORLAND__ > 0x0551
+typedef tuple<B(A::*)(C&), A&> t7;
+#endif
+
+// -----------------------------------------------------------------------
+// -tuple construction tests ---------------------------------------------
+// -----------------------------------------------------------------------
+
+
+no_copy y;
+tuple<no_copy&> x = tuple<no_copy&>(y); // ok
+
+char cs[10];
+tuple<char(&)[10]> v2(cs); // ok
+
+void
+construction_test()
+{
+
+ // Note, the get function can be called without the tuples:: qualifier,
+ // as it is lifted to namespace boost with a "using tuples::get" but
+ // MSVC 6.0 just cannot find get without the namespace qualifier
+
+ tuple<int> t1;
+ BOOST_CHECK(get<0>(t1) == int());
+
+ tuple<float> t2(5.5f);
+ BOOST_CHECK(get<0>(t2) > 5.4f && get<0>(t2) < 5.6f);
+
+ tuple<foo> t3(foo(12));
+ BOOST_CHECK(get<0>(t3) == foo(12));
+
+ tuple<double> t4(t2);
+ BOOST_CHECK(get<0>(t4) > 5.4 && get<0>(t4) < 5.6);
+
+ tuple<int, float> t5;
+ BOOST_CHECK(get<0>(t5) == int());
+ BOOST_CHECK(get<1>(t5) == float());
+
+ tuple<int, float> t6(12, 5.5f);
+ BOOST_CHECK(get<0>(t6) == 12);
+ BOOST_CHECK(get<1>(t6) > 5.4f && get<1>(t6) < 5.6f);
+
+ tuple<int, float> t7(t6);
+ BOOST_CHECK(get<0>(t7) == 12);
+ BOOST_CHECK(get<1>(t7) > 5.4f && get<1>(t7) < 5.6f);
+
+ tuple<long, double> t8(t6);
+ BOOST_CHECK(get<0>(t8) == 12);
+ BOOST_CHECK(get<1>(t8) > 5.4f && get<1>(t8) < 5.6f);
+
+ dummy(
+ tuple<no_def_constructor, no_def_constructor, no_def_constructor>(
+ std::string("Jaba"), // ok, since the default
+ std::string("Daba"), // constructor is not used
+ std::string("Doo")
+ )
+ );
+
+// testing default values
+ dummy(tuple<int, double>());
+ dummy(tuple<int, double>(1));
+ dummy(tuple<int, double>(1,3.14));
+
+
+ // dummy(tuple<double&>()); // should fail, not defaults for references
+ // dummy(tuple<const double&>()); // likewise
+
+ double dd = 5;
+ dummy(tuple<double&>(dd)); // ok
+
+ dummy(tuple<const double&>(dd+3.14)); // ok, but dangerous
+
+ // dummy(tuple<double&>(dd+3.14)); // should fail,
+ // // temporary to non-const reference
+}
+
+
+// ----------------------------------------------------------------------------
+// - testing element access ---------------------------------------------------
+// ----------------------------------------------------------------------------
+
+void element_access_test()
+{
+ double d = 2.7;
+ A a;
+ tuple<int, double&, const A&, int> t(1, d, a, 2);
+ const tuple<int, double&, const A, int> ct = t;
+
+ int i = get<0>(t);
+ int i2 = get<3>(t);
+
+ BOOST_CHECK(i == 1 && i2 == 2);
+
+ int j = get<0>(ct);
+ BOOST_CHECK(j == 1);
+
+ get<0>(t) = 5;
+ BOOST_CHECK(t.head == 5);
+
+ // get<0>(ct) = 5; // can't assign to const
+
+ double e = get<1>(t);
+ BOOST_CHECK(e > 2.69 && e < 2.71);
+
+ get<1>(t) = 3.14+i;
+ BOOST_CHECK(get<1>(t) > 4.13 && get<1>(t) < 4.15);
+
+ // get<4>(t) = A(); // can't assign to const
+ // dummy(get<5>(ct)); // illegal index
+
+ ++get<0>(t);
+ BOOST_CHECK(get<0>(t) == 6);
+
+ BOOST_STATIC_ASSERT((boost::is_const<boost::tuples::element<0, tuple<int, float> >::type>::value != true));
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ BOOST_STATIC_ASSERT((boost::is_const<boost::tuples::element<0, const tuple<int, float> >::type>::value));
+#endif
+
+ BOOST_STATIC_ASSERT((boost::is_const<boost::tuples::element<1, tuple<int, float> >::type>::value != true));
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ BOOST_STATIC_ASSERT((boost::is_const<boost::tuples::element<1, const tuple<int, float> >::type>::value));
+#endif
+
+
+ dummy(i); dummy(i2); dummy(j); dummy(e); // avoid warns for unused variables
+}
+
+
+// ----------------------------------------------------------------------------
+// - copying tuples -----------------------------------------------------------
+// ----------------------------------------------------------------------------
+
+
+
+void
+copy_test()
+{
+ tuple<int, char> t1(4, 'a');
+ tuple<int, char> t2(5, 'b');
+ t2 = t1;
+ BOOST_CHECK(get<0>(t1) == get<0>(t2));
+ BOOST_CHECK(get<1>(t1) == get<1>(t2));
+
+ tuple<long, std::string> t3(2, "a");
+ t3 = t1;
+ BOOST_CHECK((double)get<0>(t1) == get<0>(t3));
+ BOOST_CHECK(get<1>(t1) == get<1>(t3)[0]);
+
+// testing copy and assignment with implicit conversions between elements
+// testing tie
+
+ tuple<char, BB*, BB, DD> t;
+ tuple<int, AA*, CC, CC> a(t);
+ a = t;
+
+ int i; char c; double d;
+ tie(i, c, d) = make_tuple(1, 'a', 5.5);
+
+ BOOST_CHECK(i==1);
+ BOOST_CHECK(c=='a');
+ BOOST_CHECK(d>5.4 && d<5.6);
+}
+
+void
+mutate_test()
+{
+ tuple<int, float, bool, foo> t1(5, 12.2f, true, foo(4));
+ get<0>(t1) = 6;
+ get<1>(t1) = 2.2f;
+ get<2>(t1) = false;
+ get<3>(t1) = foo(5);
+
+ BOOST_CHECK(get<0>(t1) == 6);
+ BOOST_CHECK(get<1>(t1) > 2.1f && get<1>(t1) < 2.3f);
+ BOOST_CHECK(get<2>(t1) == false);
+ BOOST_CHECK(get<3>(t1) == foo(5));
+}
+
+// ----------------------------------------------------------------------------
+// make_tuple tests -----------------------------------------------------------
+// ----------------------------------------------------------------------------
+
+void
+make_tuple_test()
+{
+ tuple<int, char> t1 = make_tuple(5, 'a');
+ BOOST_CHECK(get<0>(t1) == 5);
+ BOOST_CHECK(get<1>(t1) == 'a');
+
+ tuple<int, std::string> t2;
+ t2 = boost::make_tuple((short int)2, std::string("Hi"));
+ BOOST_CHECK(get<0>(t2) == 2);
+ BOOST_CHECK(get<1>(t2) == "Hi");
+
+
+ A a = A(); B b;
+ const A ca = a;
+ make_tuple(boost::cref(a), b);
+ make_tuple(boost::ref(a), b);
+ make_tuple(boost::ref(a), boost::cref(b));
+
+ make_tuple(boost::ref(ca));
+
+// the result of make_tuple is assignable:
+ BOOST_CHECK(make_tuple(2, 4, 6) ==
+ (make_tuple(1, 2, 3) = make_tuple(2, 4, 6)));
+
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ make_tuple("Donald", "Daisy"); // should work;
+#endif
+ // std::make_pair("Doesn't","Work"); // fails
+
+// You can store a reference to a function in a tuple
+ tuple<void(&)()> adf(make_tuple_test);
+
+ dummy(adf); // avoid warning for unused variable
+
+// But make_tuple doesn't work
+// with function references, since it creates a const qualified function type
+
+// make_tuple(make_tuple_test);
+
+// With function pointers, make_tuple works just fine
+
+#if !defined(__BORLANDC__) || __BORLAND__ > 0x0551
+ make_tuple(&make_tuple_test);
+#endif
+
+// NOTE:
+//
+// wrapping it the function reference with ref helps on gcc 2.95.2.
+// on edg 2.43. it results in a catastrophic error?
+
+// make_tuple(ref(foo3));
+
+// It seems that edg can't use implicitly the ref's conversion operator, e.g.:
+// typedef void (&func_t) (void);
+// func_t fref = static_cast<func_t>(ref(make_tuple_test)); // works fine
+// func_t fref = ref(make_tuple_test); // error
+
+// This is probably not a very common situation, so currently
+// I don't know how which compiler is right (JJ)
+}
+
+void
+tie_test()
+{
+ int a;
+ char b;
+ foo c(5);
+
+ tie(a, b, c) = make_tuple(2, 'a', foo(3));
+ BOOST_CHECK(a == 2);
+ BOOST_CHECK(b == 'a');
+ BOOST_CHECK(c == foo(3));
+
+ tie(a, tuples::ignore, c) = make_tuple((short int)5, false, foo(5));
+ BOOST_CHECK(a == 5);
+ BOOST_CHECK(b == 'a');
+ BOOST_CHECK(c == foo(5));
+
+// testing assignment from std::pair
+ int i, j;
+ tie (i, j) = std::make_pair(1, 2);
+ BOOST_CHECK(i == 1 && j == 2);
+
+ tuple<int, int, float> ta;
+#ifdef E11
+ ta = std::make_pair(1, 2); // should fail, tuple is of length 3, not 2
+#endif
+
+ dummy(ta);
+}
+
+
+// ----------------------------------------------------------------------------
+// - testing tuple equality -------------------------------------------------
+// ----------------------------------------------------------------------------
+
+void
+equality_test()
+{
+ tuple<int, char> t1(5, 'a');
+ tuple<int, char> t2(5, 'a');
+ BOOST_CHECK(t1 == t2);
+
+ tuple<int, char> t3(5, 'b');
+ tuple<int, char> t4(2, 'a');
+ BOOST_CHECK(t1 != t3);
+ BOOST_CHECK(t1 != t4);
+ BOOST_CHECK(!(t1 != t2));
+}
+
+
+// ----------------------------------------------------------------------------
+// - testing tuple comparisons -----------------------------------------------
+// ----------------------------------------------------------------------------
+
+void
+ordering_test()
+{
+ tuple<int, float> t1(4, 3.3f);
+ tuple<short, float> t2(5, 3.3f);
+ tuple<long, double> t3(5, 4.4);
+ BOOST_CHECK(t1 < t2);
+ BOOST_CHECK(t1 <= t2);
+ BOOST_CHECK(t2 > t1);
+ BOOST_CHECK(t2 >= t1);
+ BOOST_CHECK(t2 < t3);
+ BOOST_CHECK(t2 <= t3);
+ BOOST_CHECK(t3 > t2);
+ BOOST_CHECK(t3 >= t2);
+
+}
+
+
+// ----------------------------------------------------------------------------
+// - testing cons lists -------------------------------------------------------
+// ----------------------------------------------------------------------------
+void cons_test()
+{
+ using tuples::cons;
+ using tuples::null_type;
+
+ cons<volatile float, null_type> a(1, null_type());
+ cons<const int, cons<volatile float, null_type> > b(2,a);
+ int i = 3;
+ cons<int&, cons<const int, cons<volatile float, null_type> > > c(i, b);
+ BOOST_CHECK(make_tuple(3,2,1)==c);
+
+ cons<char, cons<int, cons<float, null_type> > > x;
+ dummy(x);
+}
+
+// ----------------------------------------------------------------------------
+// - testing const tuples -----------------------------------------------------
+// ----------------------------------------------------------------------------
+void const_tuple_test()
+{
+ const tuple<int, float> t1(5, 3.3f);
+ BOOST_CHECK(get<0>(t1) == 5);
+ BOOST_CHECK(get<1>(t1) == 3.3f);
+}
+
+// ----------------------------------------------------------------------------
+// - testing length -----------------------------------------------------------
+// ----------------------------------------------------------------------------
+void tuple_length_test()
+{
+ typedef tuple<int, float, double> t1;
+ using tuples::cons;
+ typedef cons<int, cons< float, cons <double, tuples::null_type> > > t1_cons;
+ typedef tuple<> t2;
+ typedef tuples::null_type t3;
+
+ BOOST_STATIC_ASSERT(tuples::length<t1>::value == 3);
+ BOOST_STATIC_ASSERT(tuples::length<t1_cons>::value == 3);
+ BOOST_STATIC_ASSERT(tuples::length<t2>::value == 0);
+ BOOST_STATIC_ASSERT(tuples::length<t3>::value == 0);
+
+}
+
+// ----------------------------------------------------------------------------
+// - testing swap -----------------------------------------------------------
+// ----------------------------------------------------------------------------
+void tuple_swap_test()
+{
+ tuple<int, float, double> t1(1, 2.0f, 3.0), t2(4, 5.0f, 6.0);
+ swap(t1, t2);
+ BOOST_CHECK(get<0>(t1) == 4);
+ BOOST_CHECK(get<1>(t1) == 5.0f);
+ BOOST_CHECK(get<2>(t1) == 6.0);
+ BOOST_CHECK(get<0>(t2) == 1);
+ BOOST_CHECK(get<1>(t2) == 2.0f);
+ BOOST_CHECK(get<2>(t2) == 3.0);
+
+ int i = 1,j = 2;
+ boost::tuple<int&> t3(i), t4(j);
+ swap(t3, t4);
+ BOOST_CHECK(i == 2);
+ BOOST_CHECK(j == 1);
+}
+
+
+
+// ----------------------------------------------------------------------------
+// - main ---------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+
+int test_main(int, char *[]) {
+
+ construction_test();
+ element_access_test();
+ copy_test();
+ mutate_test();
+ make_tuple_test();
+ tie_test();
+ equality_test();
+ ordering_test();
+ cons_test();
+ const_tuple_test();
+ tuple_length_test();
+ tuple_swap_test();
+ return 0;
+}
+
+
+
+
+
+
+