191 lines
7.1 KiB
Plaintext
191 lines
7.1 KiB
Plaintext
[/
|
|
/ 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]
|