File: array-article.html

package info (click to toggle)
boost 1.27.0-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 19,908 kB
  • ctags: 26,546
  • sloc: cpp: 122,225; ansic: 10,956; python: 4,412; sh: 855; yacc: 803; makefile: 257; perl: 165; lex: 90; csh: 6
file content (234 lines) | stat: -rw-r--r-- 9,657 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
<HTML><HEAD>
<!!---------------------------------------------------------------------->
<!! Copyright (C) 1998 Dietmar Kuehl, Claas Solutions GmbH >
<!!>
<!! Permission to use, copy, modify, distribute and sell this >
<!! software for any purpose is hereby granted without fee, provided >
<!! that the above copyright notice appears in all copies and that >
<!! both that copyright notice and this permission notice appear in >
<!! supporting documentation. Dietmar Kuehl and Claas Solutions make no >
<!! representations about the suitability of this software for any >
<!! purpose. It is provided "as is" without express or implied warranty. >
<!!---------------------------------------------------------------------->
<TITLE>array-article.3</TITLE>
</HEAD>
<BODY BGCOLOR=white LINK="0000FF" VLINK="800080">
<IMG src=../../c++boost.gif alt="c++boost.gif (8819 bytes)" align=center width=277 height=86><BR>
<BR>
<SPACER TYPE=VERTICAL SIZE=40>
<H1>STL and Built-in Arrays</H1>
<H1>Abstract</H1>

Built-in arrays are supposed to fit into the STL framework. However,
in the rare case where built-in array are suitable at all, it is not
that easy to use them because there is no obvious way to determine
their size. This can, however, be changed using a bunch of simple
template classes.


  <A NAME="Introduction"><H1>Introduction</H1></A>


The Standard Template Library (STL; originally specified and
implemented by Alexander Stepanov and Meng Lee; see eg.
"The STL Tutorial and Reference Guide", D.Musser & A.Saini, Addison-Wesley, for
a tutorial) was designed to be applicable to all sequences, as long as
a small set of requirements is fulfilled. Especially, the STL was
designed to be applicable to built-in arrays (a "built-in array" is
the kind of array supported by the core language. Other kinds of
arrays, like e.g. <nobr><tt>vector</tt></nobr> or <nobr><tt>deque</tt></nobr>, are supported by some
library like the standard C++ library.)  Unfortunately, there is no
way to define member functions for built-in arrays such that there is
no way to provide complete STL support for built-in arrays. In this
article this problem is addressed together with a discussion where
this is in fact a problem. Also a potential solution is proposed.
	
	<A NAME="Background"><H1>Background</H1></A>


Before discussing how to apply STL algorithms to built-in arrays, a
brief discussion of the utility of built-in arrays is appropriate.
This is because often there is neither a need nor an advantage to use
built-in arrays in favor of some array class. The C++ built-in arrays
are inherited from C and they are incorportated into the C++ language
such that compatibility to C is not broken.  Due to this problem and
to some other design decisions, built-in arrays in C++ have some
problems (note that these are not present in C):

	<UL>
<LI>

		For C compatility it is necessary that there is a conversion from
		a built-in array to a pointer. This turns into a problem if objects of
		a derived class are stored in the array: It is possible to assign a
		pointer to the array to a pointer to a base object. However, pointer
		arithmetic with such a pointer will fail miserably and the compiler
		has in general no way to detect this problem to issue a diagnostic.
	
<LI>


    <nobr><tt>delete[]</tt></nobr> has to be used to release built-in arrays
    alloated with new. Since non-array objects have to be released with
    <nobr><tt>delete</tt></nobr> this is rather error prone and there is again no complete
    compiler support possible. One implication of the necessity to release
    array objects with <nobr><tt>delete[]</tt></nobr> instead of <nobr><tt>delete</tt></nobr> is that the class
    <nobr><tt>auto_ptr</tt></nobr> cannot be used to release dynamically allocated built-in
		arrays.

	
<LI>

		To store objects of some class in a built-in array, the class has to
		have a default constructor (unless the array is explicitly initialized;
		see below).
	
</UL>


Due to these problems it is advisable to avoid the use of built-in
arrays and to use some array classes instead. The main application of
built-in arrays, especially if they are dynamically sized and thus
stored on the free store, is the representation of array classes (even
there the use of built-in array is often limited to the use of the
pointer arithmetic to avoid requiring a default constructor; but the
implementation of array classes is not topic of this article). If
built-in arrays are used as the representation of some array classes,
there is no real problem with the lacking support for some STL stuff
since this can easily be added by the implementation of the array
class.

However, there is another important application of built-in arrays
which cannot be substituted conveniently using array classes:
Explicitly initialized arrays. Here is an example

         <P>

	 <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
  class T {
  public:
    T(int);
    // ...
  };

  T tarray[] = { T(1), T(2), T(3) };
	 </PRE></TD></TABLE>


The notation is extremely convient, especially since it it not
required to explicitly provide the number of elements. Still, it has a
problem: It is not immediately apparent how to figure out the number
of elements.  Normally, the size of a statically sized built-in array
is determined using some macro like this:

                <P>

		<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
  #define array_size(array) (sizeof(array)/sizeof(array[0]))
		</PRE></TD></TABLE>


But this macro has a problem itself: It can be applied to a pointer
where it does not compute what might be expected. The sizeof operator
returns the size of its argument even if its argument is a pointer to
an array object. Hence the macro will not determine the number of
elements in the array although it is syntactically correct. It does
return the size of the pointer divided by the size of an array
element. Thus, the <nobr><tt>array_size</tt></nobr> macro will return zero in most cases if
it is applied to a pointer since in most cases the size of a pointer
will be smaller than the size of the object pointed to. Actually,
thing can become even worse: It is possible to allocate an array
without elements. Applying this macro to an array without elements
will result in undefined behavior.

  
  <A NAME="The Solution"><H1>The Solution</H1></A>


Fortunately, there is a less error prone approach to determine the
size of a built-in array: A template function which only accepts
built-in arrays as argument can be used to determine the size of a
statically sized array. Here is such a template function:

    <P>

    <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
  template &lt;class T, int sz&gt;
  int size(T (&array)[sz])
  { return sz; }
    </PRE></TD></TABLE>


This template function can be applied to all statically sized array
objects but not to mere pointers or to dynamically allocated
arrays. In contrast to the macro, the compiler can detect attempts for
false applications and reports an error. Of course, templates
functions <nobr><tt>begin()</tt></nobr> and <nobr><tt>end()</tt></nobr> yielding pointers to the beginning and
the end of an array can also be defined. This makes it easy to apply
STL algorithms to statically sized built-in arrays.

Actually, nearly all of the requirements for containers can be changed
to turn built-in array into containers. The type definitions can be
implemented using traits classes like it is done in the standard C++
library e.g. for iterators. Functions can be implemented as global
functions instead of (or for real container classes in addtion to)
member functions. Only the operators cannot be implemented for
built-in arrays.
  
  <A NAME="What Happened Since this Article was Written?"><H1>What Happened Since this Article was Written?</H1></A>

After writing this article I discussed some variations with people
on UseNet. The basic result is that it would be reasonable to have
global template functions <nobr><tt>size()</tt></nobr>, <nobr><tt>begin()</tt></nobr>, and
<nobr><tt>end()</tt></nobr> which map to the corresponding container functions. These
functions would then be specialized for the array case. This makes it
possible to use containers and built-in array identically.

In the UseNet discussions in comp.lang.c++.moderated it was
observed that the <nobr><tt>size()</tt></nobr> function cannot be used to
produce a constant integral expression, as needed in some
situations. However, this can be done with a slightly different
approach:

    <P>

    <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
      template &lt;class T, int sz&gt;
      char[sz] sizer(T (&array)[sz]);
    </PRE></TD></TABLE>


With this definition, a constant integral expression with the
size of an array can be obtained like this:

    <P>

    <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
      sizeof(sizer(array));
    </PRE></TD></TABLE>


I have packaged and documented all this stuff and have submitted
it to the <A HREF="http://www.boost.org/">Boost library</A>.
  
  <A NAME="See Also"><H1>See Also</H1></A>

    <A HREF="array_traits.html">array_traits(3)</A>
  
<HR>

Copyright &copy 1998 <A HREF=http://www.claas-solutions.de/kuehl>Dietmar K&uuml;hl</A> (<A HREF="mailto:dietmar.kuehl@claas-solutions.de">dietmar.kuehl@claas-solutions.de</A>)<BR>
<a href="http://www.claas-solutions.de/">Claas Solutions GmbH</a>
</FONT></FONT>
</BODY></HTML>