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
|
<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_traits.3</title>
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
</head>
<body bgcolor="white" link="0000FF" vlink="800080">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86"><a href="../../boost/array_traits.hpp">array_traits.hpp</a></h1>
<h1>Abstract</h1>
Although STL somewhat supports built-in arrays, the standard library provides no
support for getting iterators to built-in arrays. While getting an iterator to
the beginning of an array is trivial, getting a past-the-end iterator is much
harder, if not impossible (at least portably). However, it is possible to get a
past-the-end iterator for statically sized built-in arrays. This component
provides functions for better support of built-in arrays.<a name="Synopsis">
<h1>Synopsis</h1>
</a>
<table border="0" cellspacing="0" cellpadding="0" cols="2">
<tr>
<td width="30" valign="TOP"></td>
<td>
<pre>
#include "boost/array_traits.hpp"
namespace boost
{
template <typename Container>
struct array_traits
{
typedef ... iterator;
typedef ... size_type;
static iterator begin();
static iterator end();
static size_type size();
};
template <typename Container>
array_traits<Container>::iterator begin(Container &c);
template <typename Container>
array_traits<Container>::iterator end(Container &c);
template <typename Container>
array_traits<Container>::size_type size(Container &c);
template <typename T, unsigned long sz>
char (&sizer(T (&)[sz]))[sz];
}
</pre>
</td>
</table>
<a name="Description">
<h1>Description</h1>
</a>The header <nobr><tt>boost/array_traits.hpp</tt></nobr> declares one
template class and a set of functions which can be used for better support of
statically sized built-in arrays. See the <a href="array-article.html">article</a>
about built-in arrays for a rationale why and under which constraints built-in
arrays are still useful (for most applications, container classes, whether from
the standard library, some third party, or self-written, are superior than
built-in arrays but there are a few exceptions to this rule).
<p>The template class <nobr><tt>array_traits</tt></nobr> is mainly an auxiliary
class used by the functions to get a consistent interface. It is specialized for
statically sized arrays and constant containers. The former does not explicitly
define an iterator type and the methods to access the beginning, the end, and
the size of this container is very different from the approach taken for STL
containers. It is necessary to specialize for constant containers because the
iterator type is a different one than for non-constant containers (<nobr><tt>const_iterator</tt></nobr>
instead of <nobr><tt>iterator</tt></nobr>).
<p>The functions <nobr><tt>begin()</tt></nobr>, <nobr><tt>end()</tt></nobr>, and
<nobr><tt>size()</tt></nobr> can be used to replace the corresponding container
member functions: For STL conformant containers, these functions simply call the
corresponding container member functions. However, for statically sized built-in
arrays, they behave different. In this case, <nobr><tt>begin()</tt></nobr>
simply returns a pointer to the array (the type passed to the function <nobr><tt>begin()</tt></nobr>
is <nobr><tt>T (&)[size]</tt></nobr>, not <nobr><tt>T*</tt></nobr>), <nobr><tt>end()</tt></nobr>
converts the argument to a pointer and adds the size of the array, and <nobr><tt>size()</tt></nobr>
returns the size.
<p>Here is a sample program using these functions:
<p>
<table border="0" cellspacing="0" cellpadding="0" cols="2">
<tr>
<td width="30" valign="TOP"></td>
<td>
<pre>
#include "boost/array_traits.hpp"
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::vector<int> vec(boost::begin(arr), boost::end(arr));
std::ostream_iterator<int> oit(std::cout, " ");
std::cout << "size: " << boost::size(arr) << "\n";
std::copy(boost::begin(arr), boost::end(arr), oit);
std::cout << "\n";
std::cout << "size: " << boost::size(vec) << "\n";
std::copy(boost::begin(vec), boost::end(vec), oit);
std::cout << "\n";
return 0;
}
</pre>
</td>
</table>
Note that this example uses absolutely identical code to print the array and the
vector. Using the same code is essential when writing templates. However, using <nobr><tt>end(array)</tt></nobr>
instead of either hardcoding the size of the array or using some macro is also
convenient in other contexts when a statically size array is used (using a macro
for this is as convenient as using the function <nobr><tt>end()</tt></nobr> but
it is not safe: the macro could be called on a pointer, too, yielding false
results).
<p>Actually, this example should use a template function which gets the
container as argument. This is not used because none of the compilers used to
test this code could compile it...<a name="Bugs">
<h1>Bugs</h1>
</a>Currently, this code needs (b)leading edge compilers. Thus, only few
compilers compile this code successfully. I was able to get the code working for
egcs-2.92.23 (that is, the snapshot from 1998-11-22) and EDG-2.39 but I needed
some extra code for both compilers to make it work. Although this code should
not be harmful to standard conforming compilers, it should be remove once it is
no longer necessary. The only other compiler I tested was MSVC++ 6.0 but this
failed with no hope to make things work... (this compiler already flagged errors
when only the array version of the three functions were used; I gave up before
coming around to test whether partial specialization needed for <nobr><tt>array_traits</tt></nobr>
works).
<p>The result of the <nobr><tt>size()</tt></nobr> function cannot be used as an
integral constant. This is the major flaw with this code. It is possible to
write a macro which is an integral constant... However, in a discussion in
comp.lang.c++.moderated a safe method for getting the size of an array as
integral constant was proposed. The basic idea is to use the <nobr><tt>sizeof</tt></nobr>
operator to a function returning a reference to an appropriately sized array of <nobr><tt>char</tt></nobr>s:
The result of the <nobr><tt>sizeof</tt></nobr> operator applied to this function
can be used as an integral constant. To do this, the function <nobr><tt>sizer()</tt></nobr>
is declared (it is not necessary to define this function since the argument to
the <nobr><tt>sizeof</tt></nobr> operator is never evaluated) is declared in <nobr><tt>boost/array_traits.hpp</tt></nobr>.
Here is an example:
<p>
<table border="0" cellspacing="0" cellpadding="0" cols="2">
<tr>
<td width="30" valign="TOP"></td>
<td>
<pre>
#include "boost/array_traits.hpp"
#include <algorithm>
int main()
{
int source[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int destination[sizeof(boost::sizer(source))];
std::copy(boost::begin(source), boost::end(source), boost::begin(destination));
}
</pre>
</td>
</table>
<a name="See Also">
<h1>See Also</h1>
</a><a href="array-article.html">array-article(3)</a>
<h1>History</h1>
<p>The header was previously named <code>array.hpp</code></p>
<hr>
Copyright 1998 <a href="http://www.claas-solutions.de/kuehl">Dietmar Khl</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>
</body>
</html>
|