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