bf(C++) offers a emi(generalized pair) container: the emi(tuple), covered in
this section.  Before tuples can be used the header file tthi(tuple) must be
included.

Whereas tt(std::pair) containers have limited functionality and only support
two members, tuples have slightly more functionality and may contain an
unlimited number of different data types. In that respect a tuple can be
considered the `template's answer to bf(C)'s struct'.

A tuple's generic declaration (and definition) uses the variadic template
notation:
        verb(    template <class ...Types>
    class tuple;)

Here is an example of its use:
        verb(    using tuple_idsc = std::tuple<int, double &, std::string, char const *>;

    double pi = 3.14;
    tuple_idsc idsc(59, pi, "hello", "fixed");

    // access a field:
    std::get<2>(idsc) = "hello world";)

The hi(get)tt(std::get<idx>(tupleObject)) function template returns a
reference to the tt(idx)+sups(th) (zero based) field of the tuple
tt(tupleObject). The index is specified as the function template's non-type
template argument.

    Type-based tuple addressing (hi(tuples: type based addressing)) can be
used for tuple types used once in a tuple definition (if the same type is used
repeatedly referring to that type introduces an ambiguity). The next example
shows how to refer to the elements in the above example by type:
        verb(    get<int>(idsc)              // 59
    get<double &>(idsc)         // 3.14
    get<string>(idsc)           // "hello"s
    get<char const *>(idsc)     // "fixed")

Tuples may be constructed without specifying initial values. Primitive
types are initialized to zeroes; class type fields are initialized by their
default constructors. Be aware that in some situations the construction of a
tuple may succeed but its use may fail. Consider:
        verb(    tuple<int &> empty;
    cout << get<0>(empty);)

Here the tuple tt(empty) cannot be used as its tt(int &) field is an
undefined reference. However, tt(empty)'s construction succeeds.

    Tuples may be assigned to each other if their type lists are identical; if
supported by their constituent types copy constructors are available as
well. Copy construction and assignment is also available if a right-hand type
can be converted to its matching left-hand type or if the left-hand type can
be constructed from the matching right-hand type. Tuples
(matching in number and (convertible) types) can be compared using relational
operators as long as their constituent types support comparisons. In this
respect tuples are like pairs.

    Tuples offer the following static elements (using compile-time
initialization):
    itemization(
    itht(tuple_size)(std::tuple_size<Tuple>::value) returns the number of
types defined for the tuple type tt(Tuple). Example:
        verb(cout << tuple_size<tuple_idsc>::value << '\n';  // displays: 4)

itht(tuple_element)(std::tuple_element<idx, Tuple>::type)
        returns the type of element tt(idx) of tt(Tuple). Example:
        verb(tuple_element<2, tuple_idsc>::type text;  // defines std::string text)

)

    The unpack operator can also be used to forward the arguments of a
constructor to a tuple data member. Consider a class tt(Wrapper) that is
defined as a variadic template:
        verb(    template <typename ...Params>
    class Wrapper
    {
        ...
        public:
            Wrapper(Params &&...params);
    };)

This class may be given a tuple data member which should be initialized by
the types and values that are used when initializing an object of the class
 hi(perfect forwarding: to data members) tt(Wrapper) using perfect
forwarding. Comparable to the way a class may inherit from its template types
(cf. section ref(UNPACK)) it may forward its types and constructor arguments
to its tuple data member:
        verb(    template <typename ...Params>
    class Wrapper
    {
        std::tuple<Params...> d_tuple;     // same types as used for
                                            // Wrapper itself
        public:
            Wrapper(Params &&...params)
            :                               // initialize d_tuple with
                                            // Wrapper's arguments
                d_tuple(std::forward<Params>(params)...)
            {}
    };)

