Re: std::array - if only it knew its size
Am 05.04.2011 18:52, schrieb Ricky65:
I am pleased that C++0x includes a container for fixed-size arrays -
std::array. The obvious advantages being that, unlike built in arrays,
it's easy to get the size of the array using the size() method and the
array doesn't "decay" to a pointer like a built in array and so on. It
goes without saying that these problems with built in arrays cause a
lot of bugs. However, I feel there is a significant shortcoming with
this container - std::array cannot deduce the size of the array from
the initializer list. From what I understand, this is the only
advantage built in arrays have over std::array. This limitation can be
a problem when initializing an array with lots of items.
Yes, I agree
For example, I have a lot of integers or strings to initialize an
array with, and as there are so many I may not know the total number
of items at the moment of declaration without counting them all. This
can be quite a laborious and time consuming task and is something I'd
rather not have to do. Worst still, as the initializer-list
constructor is being added to the other standard containers, this is
only a problem with std::array. Because of this, I suspect some
programmers in C++0x may choose to initialize a std::vector (or
another container) where std::array would be more appropriate.
For example,
std::vector<int> myintvec = {3, 9, 11, 13 /* ... */}; //ok in c++0x
using initializer_list. works on GCC 4.6
std::array<int> myintarray = {3, 9, 11, 13 /* ... */}; //oh dear,
not possible
Above should have the same functionality of
int myintarray [] = {3, 9, 11, 13 /* ... */};
Sadly, std::array is like the oddball of the containers in this
regard. Also, doesn't this also go against the "uniform
initialization" goal of C++0x? I don't have to specify the number of
items in the initializer list for the other containers such as
std::vector, but I do for std::array. Uniform initialization... except
for std::array.
I can also see this being a problem for novices as they may
intuitively expect std::array to be initialized in the same way as the
other containers and may be surprised to find out that it doesn't work
like they presumed it should.
A lot of programmers would probably rather use this container than a
built in array for fixed-size arrays but with this caveat I suspect
that they may be deterred from adopting it.
This is how I work around this limitation at the moment. In Visual C++
2010 I first declare the array as a built in array e.g. "int
myintarray [] = {3, 9, 11, 13 /* ... */};" . I then use IntelliSense
to get the number of items in the array initializer list e.g. 232, and
finally I replace the built in array with e.g. "std::array<int,
232>myintarray = {3, 9, 11, 13 /* ... */}; ". A far from ideal
workaround. If you know of a less cumbersome way, please share.
It's also an inconvenience if I later want to add more items to the
array initializer list. I must be careful to keep track of the number
of items I am adding so I can update the size parameter accordingly.
If I lose track of the number of items in the initializer list I have
the inconvenience of obtaining the size again.
I'm aware std::array is an aggregate and as such has no constructors
so I assume an initializer-list constructor is no good here. My
understanding is that, at the present time, there is no provision in
the language to deduce the size of the array from the initializer
list. Therefore, I believe this functionality should be added to the
language. Surely it wouldn't be too hard to implement? My opinion is
that somehow this functionality needs to get in there or std::array
may get shunned by many programmers for the aforementioned reason and
that would be a quite a shame and a missed opportunity.
Anyway, that's my two pennies worth on std::array. I will be
interested in reading your replies.
I think what you want is something like make_array as suggested in
http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#851
This issues has been deferred as NAD future, because there was no pressing need to provide this for C++0x.
Until that point you can simply define your own make_array as described in the issue:
#include <type_traits>
#include <utility>
#include <array>
template <typename... T>
std::array<typename std::decay<typename std::common_type<T...>::type
::type, sizeof...(T)>
make_array(T&&... t)
{
typedef typename std::decay<typename std::common_type<T...>::type
>::type U;
std::array<U, sizeof...(T)> result = {
static_cast<U>(std::forward<T>(t))...
};
return result;
}
int main()
{
auto a = make_array(1, 2); // OK: std::array<int, 2>
auto b = make_array(1, 1.2, 2u); // OK: std::array<double, 3>
}
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]