123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- [/
- / 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]
|