1[/ 2 / Copyright (c) 2001 Jaakko J�rvi 3 / 4 / Distributed under the Boost Software License, Version 1.0. (See 5 / accompanying file LICENSE_1_0.txt or copy at 6 / http://www.boost.org/LICENSE_1_0.txt) 7 /] 8 9[article Design decisions rationale 10 [quickbook 1.6] 11 [id design_decisions_rationale] 12 [copyright 2001 Jaakko J\u00E4rvi] 13 [license Distributed under the 14 [@http://boost.org/LICENSE_1_0.txt Boost Software License, 15 Version 1.0]. 16 ] 17] 18 19[template simplesect[title] 20[block '''<simplesect><title>'''[title]'''</title>''']] 21 22[template endsimplesect[] 23[block '''</simplesect>''']] 24 25[section About namespaces] 26 27There was a discussion about whether tuples should be in a separate namespace 28or directly in the `boost` namespace. The common principle is that domain 29libraries (like /graph/, /python/) should be on a separate subnamespace, while 30utility like libraries directly in the boost namespace. Tuples are somewhere 31in between, as the tuple template is clearly a general utility, but the 32library introduces quite a lot of names in addition to just the tuple template. 33Tuples were originally under a subnamespace. As a result of the discussion, 34tuple definitions were moved directly under the `boost` namespace. As a result 35of a continued discussion, the subnamespace was reintroduced. The final (I 36truly hope so) solution is now to have all definitions in namespace 37`::boost::tuples`, and the most common names in the `::boost` namespace as well. 38This is accomplished with using declarations (suggested by Dave Abrahams): 39 40 namespace boost { 41 namespace tuples { 42 ... 43 // All library code 44 ... 45 } 46 using tuples::tuple; 47 using tuples::make_tuple; 48 using tuples::tie; 49 using tuples::get; 50 } 51 52With this arrangement, tuple creation with direct constructor calls, 53`make_tuple` or `tie` functions do not need the namespace qualifier. Further, 54all functions that manipulate tuples are found with Koenig-lookup. The only 55exceptions are the `get<N>` functions, which are always called with an 56explicitly qualified template argument, and thus Koenig-lookup does not apply. 57Therefore, `get` is lifted to `::boost` namespace with a using declaration. 58Hence, the interface for an application programmer is in practice under the 59namespace `::boost`. 60 61The other names, forming an interface for library writers (cons lists, 62metafunctions manipulating cons lists, ...) remain in the subnamespace 63`::boost::tuples`. Note, that the names `ignore`, `set_open`, `set_close` and 64`set_delimiter` are considered to be part of the application programmer's 65interface, but are still not under `boost` namespace. The reason being the 66danger for name clashes for these common names. Further, the usage of these 67features is probably not very frequent. 68 69[section For those who are really interested in namespaces] 70 71The subnamespace name /tuples/ raised some discussion. The rationale for not 72using the most natural name 'tuple' is to avoid having an identical name with 73the tuple template. Namespace names are, however, not generally in plural form 74in Boost libraries. First, no real trouble was reported for using the same 75name for a namespace and a class and we considered changing the name 'tuples' 76to 'tuple'. But we found some trouble after all. Both gcc and edg compilers 77reject using declarations where the namespace and class names are identical: 78 79 namespace boost { 80 namespace tuple { 81 ... tie(...); 82 class tuple; 83 ... 84 } 85 using tuple::tie; // ok 86 using tuple::tuple; // error 87 ... 88 } 89 90Note, however, that a corresponding using declaration in the global namespace 91seems to be ok: 92 93 using boost::tuple::tuple; // ok; 94 95[endsect] 96 97[endsect] 98 99[section The end mark of the cons list (`nil`, `null_type`, ...)] 100 101Tuples are internally represented as cons lists: 102 103 tuple<int, int> 104 105inherits from 106 107 cons<int, cons<int, null_type> > 108 109`null_type` is the end mark of the list. Original proposition was `nil`, but 110the name is used in MacOS, and might have caused problems, so `null_type` was 111chosen instead. Other names considered were /null_t/ and /unit/ (the empty 112tuple type in SML). 113 114Note that `null_type` is the internal representation of an empty tuple: 115`tuple<>` inherits from `null_type`. 116 117[endsect] 118 119[section Element indexing] 120 121Whether to use `0`- or `1`-based indexing was discussed more than thoroughly, 122and the following observations were made: 123 124* `0`-based indexing is 'the C++ way' and used with arrays etc. 125 126* `1`-based 'name like' indexing exists as well, eg. `bind1st`, `bind2nd`, 127 `pair::first`, etc. 128 129Tuple access with the syntax `get<N>(a)`, or `a.get<N>()` (where `a` is a 130tuple and `N` an index), was considered to be of the first category, hence, 131the index of the first element in a tuple is `0`. 132 133A suggestion to provide `1`-based 'name like' indexing with constants like 134`_1st`, `_2nd`, `_3rd`, ... was made. By suitably chosen constant types, this 135would allow alternative syntaxes: 136 137 a.get<0>() == a.get(_1st) == a[_1st] == a(_1st); 138 139We chose not to provide more than one indexing method for the following 140reasons: 141 142* `0`-based indexing might not please everyone, but once its fixed, it is less 143 confusing than having two different methods (would anyone want such 144 constants for arrays?). 145 146* Adding the other indexing scheme doesn't really provide anything new (like a 147 new feature) to the user of the library. 148 149* C++ variable and constant naming rules don't give many possibilities for 150 defining short and nice index constants (like `_1st`, ...). Let the binding 151 and lambda libraries use these for a better purpose. 152 153* The access syntax a[_1st] (or a(_1st)) is appealing, and almost made us add 154 the index constants after all. However, `0`-based subscripting is so deep in 155 C++, that we had a fear for confusion. 156 157* Such constants are easy to add. 158 159[endsect] 160 161[section Tuple comparison] 162 163The comparison operator implements lexicographical order. Other orderings were 164considered, mainly dominance /(a < b iff for each i a(i) < b(i))/. Our belief 165is, that lexicographical ordering, though not mathematically the most natural 166one, is the most frequently needed ordering in everyday programming. 167 168[endsect] 169 170[section Streaming] 171 172The characters specified with tuple stream manipulators are stored within the 173space allocated by `ios_base::xalloc`, which allocates storage for `long` type 174objects. `static_cast` is used in casting between `long` and the stream's 175character type. Streams that have character types not convertible back and 176forth to long thus fail to compile. 177 178This may be revisited at some point. The two possible solutions are: 179 180* Allow only plain `char` types as the tuple delimiters and use `widen` and 181 `narrow` to convert between the real character type of the stream. This 182 would always compile, but some calls to set manipulators might result in a 183 different character than expected (some default character). 184 185* Allocate enough space to hold the real character type of the stream. This 186 means memory for holding the delimiter characters must be allocated 187 separately, and that pointers to this memory are stored in the space 188 allocated with `ios_base::xalloc`. Any volunteers? 189 190[endsect] 191