1 | <html> |
---|
2 | |
---|
3 | <title>Design decisions rationale for Boost Tuple Library</title> |
---|
4 | |
---|
5 | <body bgcolor="#FFFFFF" text="#000000"> |
---|
6 | |
---|
7 | <IMG SRC="../../../boost.png" |
---|
8 | ALT="C++ Boost" width="277" height="86"> |
---|
9 | |
---|
10 | <h1>Tuple Library : design decisions rationale</h1> |
---|
11 | |
---|
12 | <h2>About namespaces</h2> |
---|
13 | |
---|
14 | <p> |
---|
15 | There was a discussion about whether tuples should be in a separate namespace or directly in the <code>boost</code> namespace. |
---|
16 | The common principle is that domain libraries (like <i>graph</i>, <i>python</i>) should be on a separate |
---|
17 | subnamespace, while utility like libraries directly in the <code>boost</code> namespace. |
---|
18 | 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. |
---|
19 | Tuples were originally under a subnamespace. |
---|
20 | As a result of the discussion, tuple definitions were moved directly under the <code>boost</code> namespace. |
---|
21 | As a result of a continued discussion, the subnamespace was reintroduced. |
---|
22 | The final (I truly hope so) solution is now to have all definitions in namespace <code>::boost::tuples</code>, and the most common names in the <code>::boost</code> namespace as well. |
---|
23 | This is accomplished with using declarations (suggested by Dave Abrahams): |
---|
24 | <code><pre>namespace boost { |
---|
25 | namespace tuples { |
---|
26 | ... |
---|
27 | // All library code |
---|
28 | ... |
---|
29 | } |
---|
30 | using tuples::tuple; |
---|
31 | using tuples::make_tuple; |
---|
32 | using tuples::tie; |
---|
33 | using tuples::get; |
---|
34 | } |
---|
35 | </pre></code> |
---|
36 | With this arrangement, tuple creation with direct constructor calls, <code>make_tuple</code> or <code>tie</code> functions do not need the namespace qualifier. |
---|
37 | Further, all functions that manipulate tuples are found with Koenig-lookup. |
---|
38 | The only exceptions are the <code>get<N></code> functions, which are always called with an explicitly qualified template argument, and thus Koenig-lookup does not apply. |
---|
39 | Therefore, get is lifted to <code>::boost</code> namespace with a using declaration. |
---|
40 | Hence, the interface for an application programmer is in practice under the namespace <code>::boost</code>. |
---|
41 | </p> |
---|
42 | <p> |
---|
43 | The other names, forming an interface for library writers (cons lists, metafunctions manipulating cons lists, ...) remain in the subnamespace <code>::boost::tuples</code>. |
---|
44 | Note, that the names <code>ignore</code>, <code>set_open</code>, <code>set_close</code> and <code>set_delimiter</code> are considered to be part of the application programmer's interface, but are still not under <code>boost</code> namespace. |
---|
45 | The reason being the danger for name clashes for these common names. |
---|
46 | Further, the usage of these features is probably not very frequent. |
---|
47 | </p> |
---|
48 | |
---|
49 | <h4>For those who are really interested in namespaces</h4> |
---|
50 | |
---|
51 | <p> |
---|
52 | The subnamespace name <i>tuples</i> raised some discussion. |
---|
53 | The rationale for not using the most natural name 'tuple' is to avoid having an identical name with the tuple template. |
---|
54 | Namespace names are, however, not generally in plural form in boost libraries. |
---|
55 | 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'. |
---|
56 | But we found some trouble after all. |
---|
57 | Both gcc and edg compilers reject using declarations where the namespace and class names are identical: |
---|
58 | |
---|
59 | <code><pre>namespace boost { |
---|
60 | namespace tuple { |
---|
61 | ... tie(...); |
---|
62 | class tuple; |
---|
63 | ... |
---|
64 | } |
---|
65 | using tuple::tie; // ok |
---|
66 | using tuple::tuple; // error |
---|
67 | ... |
---|
68 | } |
---|
69 | </pre></code> |
---|
70 | |
---|
71 | Note, however, that a corresponding using declaration in the global namespace seems to be ok: |
---|
72 | |
---|
73 | <code><pre> |
---|
74 | using boost::tuple::tuple; // ok; |
---|
75 | </pre></code> |
---|
76 | |
---|
77 | |
---|
78 | <h2>The end mark of the cons list (nil, null_type, ...)</h2> |
---|
79 | |
---|
80 | <p> |
---|
81 | Tuples are internally represented as <code>cons</code> lists: |
---|
82 | |
---|
83 | <code><pre>tuple<int, int> |
---|
84 | </pre></code> |
---|
85 | inherits from |
---|
86 | <code><pre>cons<int, cons<int, null_type> > |
---|
87 | </code></pre> |
---|
88 | |
---|
89 | <code>null_type</code> is the end mark of the list. Original proposition was <code>nil</code>, but the name is used in MacOS, and might have caused problems, so <code>null_type</code> was chosen instead. |
---|
90 | Other names considered were <i>null_t</i> and <i>unit</i> (the empty tuple type in SML). |
---|
91 | <p> |
---|
92 | Note that <code>null_type</code> is the internal representation of an empty tuple: <code>tuple<></code> inherits from <code>null_type</code>. |
---|
93 | </p> |
---|
94 | |
---|
95 | <h2>Element indexing</h2> |
---|
96 | |
---|
97 | <p> |
---|
98 | Whether to use 0- or 1-based indexing was discussed more than thoroughly, and the following observations were made: |
---|
99 | |
---|
100 | <ul> |
---|
101 | <li> 0-based indexing is 'the C++ way' and used with arrays etc.</li> |
---|
102 | <li> 1-based 'name like' indexing exists as well, eg. <code>bind1st</code>, <code>bind2nd</code>, <code>pair::first</code>, etc.</li> |
---|
103 | </ul> |
---|
104 | Tuple access with the syntax <code>get<N>(a)</code>, or <code>a.get<N>()</code> (where <code>a</code> is a tuple and <code>N</code> an index), was considered to be of the first category, hence, the index of the first element in a tuple is 0. |
---|
105 | |
---|
106 | <p> |
---|
107 | A suggestion to provide 1-based 'name like' indexing with constants like <code>_1st</code>, <code>_2nd</code>, <code>_3rd</code>, ... was made. |
---|
108 | By suitably chosen constant types, this would allow alternative syntaxes: |
---|
109 | |
---|
110 | <code><pre>a.get<0>() == a.get(_1st) == a[_1st] == a(_1st); |
---|
111 | </pre></code> |
---|
112 | |
---|
113 | We chose not to provide more than one indexing method for the following reasons: |
---|
114 | <ul> |
---|
115 | <li>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?).</li> |
---|
116 | <li>Adding the other indexing scheme doesn't really provide anything new (like a new feature) to the user of the library.</li> |
---|
117 | <li>C++ variable and constant naming rules don't give many possibilities for defining short and nice index constants (like <code>_1st</code>, ...). |
---|
118 | Let the binding and lambda libraries use these for a better purpose.</li> |
---|
119 | <li>The access syntax <code>a[_1st]</code> (or <code>a(_1st)</code>) 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.</li> |
---|
120 | <li> |
---|
121 | Such constants are easy to add. |
---|
122 | </li> |
---|
123 | </ul> |
---|
124 | |
---|
125 | |
---|
126 | <h2>Tuple comparison</h2> |
---|
127 | |
---|
128 | The comparison operator implements lexicographical order. |
---|
129 | Other orderings were considered, mainly dominance (<i>a < b iff for each i a(i) < b(i)</i>). |
---|
130 | Our belief is, that lexicographical ordering, though not mathematically the most natural one, is the most frequently needed ordering in everyday programming. |
---|
131 | |
---|
132 | <h2>Streaming</h2> |
---|
133 | |
---|
134 | <p> |
---|
135 | The characters specified with tuple stream manipulators are stored within the space allocated by <code>ios_base::xalloc</code>, which allocates storage for <code>long</code> type objects. |
---|
136 | <code>static_cast</code> is used in casting between <code>long</code> and the stream's character type. |
---|
137 | Streams that have character types not convertible back and forth to long thus fail to compile. |
---|
138 | |
---|
139 | This may be revisited at some point. The two possible solutions are: |
---|
140 | <ul> |
---|
141 | <li>Allow only plain <code>char</code> types as the tuple delimiters and use <code>widen</code> and <code>narrow</code> to convert between the real character type of the stream. |
---|
142 | This would always compile, but some calls to set manipulators might result in a different |
---|
143 | character than expected (some default character).</li> |
---|
144 | <li>Allocate enough space to hold the real character type of the stream. |
---|
145 | 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 <code>ios_base::xalloc</code>. |
---|
146 | Any volunteers?</li> |
---|
147 | </ul> |
---|
148 | |
---|
149 | <A href="tuple_users_guide.html">Back to the user's guide</A> |
---|
150 | <hr><p>© Copyright Jaakko Järvi 2001. |
---|
151 | </body> |
---|
152 | </html> |
---|
153 | |
---|