# Tuple Library : design decisions rationale

## About namespaces

There was a discussion about whether tuples should be in a separate namespace or directly at the `boost` namespace. The common principle is that domain libraries (like graph, python) should be on a separate sub-namespace, 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. As a result of the discussion, tuple definitions are now directly under the `boost` namespace.

#### For those who are really interested in namespaces

Note! The following discussion is not relevant for the Tuple library, as the 'no sub-namespace' decision was taken, but it may be useful for other library writers.

In the original tuple library submission, all names were under the namespace `tuples`. This brought up the issue of naming sub-namespaces. The rationale for not using the most natural name 'tuple' was to avoid having an identical name with the tuple template. Namespace names are, however, not generally in plural form in boost libraries. Further, no real trouble was reported for using the same name for a namespace and a class. But we found some trouble after all. One solution proposed to the dilemma of introducing a sub-namespace or not was as follows: use a sub-namespace but lift the most common names to the `boost` namespace with using declarations. Both gcc and edg compilers rejected such using declarations if the namespace and class names were identical: ``

    namespace boost {
      namespace tuple {
        class cons;
        class tuple;
          ...
      }
      using tuple::cons; // ok
      using tuple::tuple; // error
        ...
    }

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

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

`

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

Tuples are internally represented as `cons` lists: ``

    tuple<int, int>

inherits from `

    cons<int, cons<int, null_type> >

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

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

## Element indexing

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

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

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

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

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

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

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

## Tuple comparison

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

## Streaming

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

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

Back to the user's guide

© Copyright Jaakko Järvi 2001.