Topic: Sizes of containers and arrays
Author: James Kuyper <kuyper@wizard.net>
Date: 2000/07/25 Raw View
Chris Newton wrote:
>
> James Kuyper <kuyper@wizard.net> wrote...
> > Chris Newton wrote:
> > > James Kuyper <kuyper@wizard.net> wrote [abridged]...
> > > > Since the constructor takes an argument of type
> > > > std::vector<int>::size_type, that's what I'd recommend
> > > > using for 'type'. You shouldn't need to use a cast.
> > >
> > > My worry here was that std::vector<int>::size_type might
> > > be able to store larger numbers than size_t.
> >
> > So what? What do you think could go wrong if it could store
> > numbers too large to store in size_t?
>
> The problem stemmed from wanting to preinitialise an STL-style container
> from an array (since you can't write
> vector<char> data = {'A', 'B', 'C', ...};
> directly).
>
> We were dealing with a very large array of initialisation data,
> generated for us by another package. The volume of initialisation data
> was in danger of exceeding the limits of size_t (and hence an array) on
> our system.
In order for sizeof(array) to work correctly, the maximum size of an
array must be less than or equal to the maximum value of size_t.
However, the fact that a number will fit in size_t is no guarantee that
it can be safely used as a dimension of an array, even if that array has
a character type.
> We wanted to assign the size of the initialisation array (as a literal
> generated for us) to a suitably typed variable, so that the compiler
> would warn of any truncation, and any data that could not fit into the
> container in use. This is where the question of whether to use size_t or
> ...::size_type arose. At the same time, we wanted to maintain
Well, offhand I can't think of any reason favoring size_t over size_type
for that purpose. If your compiler warns of truncation, it will warn
with size_type. The size of the array doesn't require a size_t, and the
value is not truncated to size_t when allocating the array, so there's
no need to worry there. An attempt to construct the vector<> from the
array is likely to throw an exception if the array is too big for the
container, something that could happen for values much smaller than the
maximum value that can be stored in a size_t.
The type of exception thrown by a failed vector<> constructor is not
guaranteed by the standard, though std::bad_alloc seems a likely choice.
If you wish to avoid throwing an unknown exception from the constructor,
try the following:
#include <vector>
const std::vector<int>::size_type N=SOME_BIG_VALUE;
int array[N];
// Code initializing array
const std::vector<int> c;
try
{
c.reserve(N);
if(c.capacity >= N)
{
c.insert(c.end(), N, array);
// or c.insert(c.end(), array, array+N);
}else{
// Won't fit - error handling.
}
}
catch(std::length_error e)
{
// N was bigger than c.max_size().
// error handling
cerr << e.what();
}
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Chris Newton" <chrisnewton@no.junk.please.btinternet.com>
Date: 2000/07/24 Raw View
James Kuyper <kuyper@wizard.net> wrote...
> Chris Newton wrote:
> > James Kuyper <kuyper@wizard.net> wrote [abridged]...
> > > Since the constructor takes an argument of type
> > > std::vector<int>::size_type, that's what I'd recommend
> > > using for 'type'. You shouldn't need to use a cast.
> >
> > My worry here was that std::vector<int>::size_type might
> > be able to store larger numbers than size_t.
>
> So what? What do you think could go wrong if it could store
> numbers too large to store in size_t?
The problem stemmed from wanting to preinitialise an STL-style container
from an array (since you can't write
vector<char> data = {'A', 'B', 'C', ...};
directly).
We were dealing with a very large array of initialisation data,
generated for us by another package. The volume of initialisation data
was in danger of exceeding the limits of size_t (and hence an array) on
our system.
We wanted to assign the size of the initialisation array (as a literal
generated for us) to a suitably typed variable, so that the compiler
would warn of any truncation, and any data that could not fit into the
container in use. This is where the question of whether to use size_t or
...::size_type arose. At the same time, we wanted to maintain
portability since we hoped to move away from such a limiting system
(MS-DOS, 64K boundaries, etc.).
On reflection, we concluded that the compiler would surely raise an
error if we attempted to over-initialise an array anyway, and similarly
we wouldn't be able to copy too much data into a container, so the
problem was resolved.
Thanks for the input,
Chris
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 2000/07/19 Raw View
Chris Newton wrote:
>
> Dear all,
>
> Does the standard mandate any particular relationship between the types
> size_t and {container}::size_type? Everything seems to be
> implementation-defined, and I cannot find anything requiring a definite
> relationship.
Yes. size_t and size_type must both be unsigned. size_type can be
unsigned char, and size_t can be unsigned long, but they must both be
unsigned.
Some containers are required to have size_type be size_t. Specifically,
the default allocator for all standard containers is std::allocator<T>.
That allocator is required to have a size_type be size_t. For most
standard containers size_type is implementation defined, but for
basic_string<charT, traits,Allocator>, it is required to be
Allocator::size_type, and will therefore be size_t if no other allocator
is specified.
> Motivation: If I wish to create an array of N int, and a vector<int> of
> initial size N, what would be the appropriate type to use for the
> constant N? Can I do something like the following, or am I forced to use
> a cast?
> typedef /* something */ type;
> type N;
> int arr[N];
> vector<int> vec(N);
Since the constructor takes an argument of type
std::vector<int>::size_type, that's what I'd recommend using for 'type'.
You shouldn't need to use a cast.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Chris Newton" <chrisnewton@no.junk.please.btinternet.com>
Date: 2000/07/19 Raw View
James Kuyper <kuyper@wizard.net> wrote [abridged]...
> Chris Newton wrote:
> > Does the standard mandate any particular relationship
> > between the types size_t and {container}::size_type?
> > Everything seems to be implementation-defined, and
> > I cannot find anything requiring a definite relationship.
>
> Some containers are required to have size_type be size_t.
> Specifically, the default allocator for all standard containers
> is std::allocator<T>. That allocator is required to have a
> size_type be size_t. For most standard containers size_type
> is implementation defined, [...]
This is what confused me. Assuming I am using a standard container in a
simple way, e.g., vector<int>, how can size_type be
implementation-defined when std::allocator is required to have size_type
be size_t? Does this mean that std::vector<int>::size_type is not
necessarily the same as std::allocator<int>::size_type, even though the
latter is the allocator for the former?
Ultimately all I really want is a guarantee of one of the following
relationships between the maximum values of the types stated (and
similarly for other containers).
(a) std::vector<int>::size_type <= size_t
(b) std::vector<int>::size_type = size_t
(c) std::vector<int>::size_type => size_t
On current evidence, I'm still not sure whether such a guarantee exists.
<sigh>
No wonder that in production code most people just write "int" and have
done with it... ;-)
> > Motivation: If I wish to create an array of N int, and a
> > vector<int> of initial size N, what would be the appropriate
> > type to use for the constant N? Can I do something like the
> > following, or am I forced to use a cast?
> > typedef /* something */ type;
> > type N;
> > int arr[N];
> > vector<int> vec(N);
>
> Since the constructor takes an argument of type
> std::vector<int>::size_type, that's what I'd recommend using
> for 'type'. You shouldn't need to use a cast.
My worry here was that std::vector<int>::size_type might be able to stor
e larger numbers than size_t. Granted that's unlikely if we're talking
std::vector, since the underlying implementation is almost certainly an
array. However, we also have things like std::list, or even std::deque,
where it's quite possible. (Consider a segmented architecture, for
example, where typically arrays may not cross segment boundaries but
pointers can. Early Intel boxes suffered from a 64K segment limit, but
had "far" pointers that could include a segment, and so people used
linked lists and the like to overcome the 64K limit.)
Thanks for your insights; any further comments are welcome.
Regards,
Chris
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 2000/07/20 Raw View
Chris Newton wrote:
>
> James Kuyper <kuyper@wizard.net> wrote [abridged]...
> > Chris Newton wrote:
> > > Does the standard mandate any particular relationship
> > > between the types size_t and {container}::size_type?
> > > Everything seems to be implementation-defined, and
> > > I cannot find anything requiring a definite relationship.
> >
> > Some containers are required to have size_type be size_t.
> > Specifically, the default allocator for all standard containers
> > is std::allocator<T>. That allocator is required to have a
> > size_type be size_t. For most standard containers size_type
> > is implementation defined, [...]
>
> This is what confused me. Assuming I am using a standard container in a
> simple way, e.g., vector<int>, how can size_type be
> implementation-defined when std::allocator is required to have size_type
> be size_t? Does this mean that std::vector<int>::size_type is not
> necessarily the same as std::allocator<int>::size_type, even though the
> latter is the allocator for the former?
Exactly correct.
> Ultimately all I really want is a guarantee of one of the following
> relationships between the maximum values of the types stated (and
> similarly for other containers).
> (a) std::vector<int>::size_type <= size_t
> (b) std::vector<int>::size_type = size_t
> (c) std::vector<int>::size_type => size_t
> On current evidence, I'm still not sure whether such a guarantee exists.
Not one of those guarantees exists. Code which makes any such
assumptions is broken.
> No wonder that in production code most people just write "int" and have
> done with it... ;-)
Hopefully, only when they are certain that none of the numbers involved
will cause problems converting to and from size_type.
....
> > Since the constructor takes an argument of type
> > std::vector<int>::size_type, that's what I'd recommend using
> > for 'type'. You shouldn't need to use a cast.
>
> My worry here was that std::vector<int>::size_type might be able to stor
> e larger numbers than size_t. Granted that's unlikely if we're talking
So what? What do you think could go wrong if it could store numbers too
large to store in size_t? Properly written code shouldn't have problems
with that.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Chris Newton" <chrisnewton@no.junk.please.btinternet.com>
Date: 2000/07/18 Raw View
Dear all,
Does the standard mandate any particular relationship between the types
size_t and {container}::size_type? Everything seems to be
implementation-defined, and I cannot find anything requiring a definite
relationship.
Motivation: If I wish to create an array of N int, and a vector<int> of
initial size N, what would be the appropriate type to use for the
constant N? Can I do something like the following, or am I forced to use
a cast?
typedef /* something */ type;
type N;
int arr[N];
vector<int> vec(N);
Thanks,
Chris
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]