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