The only and imo very inconvenient caveat of std::array
is that it can't deduce its size from the initializer list like built-in C arrays, it's size must be passed as a template.
Is it possible to implement a std::array-like container (a thin wrapper around a built-in C array) with a C++11
initializer_list?
I ask because, unlike std::array, it would automatically deduce the size of the array from the initializer list which is a lot more convenient. For example:
// il_array is the hypothetical container
// automatically deduces its size from the initalizer list
il_array <int> myarr = {2, 4, 6, 7, 8};
We would also want to provide a constructor to specify the size if an initializer list was not provided. For example:
// construct a fixed size array of size 10
il_array <int> myarr2 (10);
This would also make the container more consistent with the other standard containers e.g. vector, deque and list.
To the best of my knowledge it isn't possible as the wrapped C-array e.g. T elems [size], must have constant size and initializer_list's size() member function isn't constant.
Also, I was wondering if was possible to implement such a container using a variadic template although from what I've read I don't think it's possible.
Yes, well, so long as you are willing to cheat.As Mooing Duck points out, no, not even cheating, unless the compiler implementors let you. Though, it is still possible to get close enough -- it is possible to use initializer lists and a static array that is hidden by the wrapper.This is some code I wrote for my personal toolbox. The key is to disregard the size altogether, even for the array, and let the provider container handle it; in this case,
initializer_list
who can provide the size viastd::distance
, thus avoiding client-side size explicitation (a term that I just invented, it seems).Since it is the "anyone could've come up with it" kind of code, no problems about providing it "back" to the public; in fact, I got the idea from some expert guy whose nick I don't remember at Freenode's
##c++
channel, so I guess the recognition is for them:*EDIT*ed:
Usage and declaration in C++0x mode is pretty simple (just tested with GCC 4.6 in Fedora 15), but it works with the caveats noted in the external links above, so it is apparently undefined behaviour:
However, I don't see why a compiler implementor would not implement an initializer_list of integrals as a static array anyway. Your call.
Not only it works like that, provided you can
#ifdef
the initializer constructor out of the way in pre-C++0x mode, you can actually use this in pre-C++0x; although predeclaration of the data array as its own variable will be needed, it is IMHO the closest it gets to the original intent (and it has the advantage of being usable and not causing eg.: scope issues). (also tested with the above compiler, plus Debian Wheezy's GCC):There! No "size" parameter anywhere!
Sorry, this is one feature I have not maganed to implement. The problem is how to assign the memory "statically" from an outside source, perhaps an Allocator. Assuming it could be done somehow via a helper functor
allocate
, then the constructor would be something like this:I hope this code is of help, as I see the question is more or less old.
I think you are out of luck here. The great advantage of std::array is that it is a POD and can be statically initialized.
If you have a container with a constructor taking a std::initializer_list, it would have to copy the values (unless it is just a constant reference to the initializer, which isn't very useful).
How about this one? I used
std::tuple
instead of aninitializer_list
because the number of tuple arguments are available at compile-time. Thetuple_array
class below inherits fromstd::array
and adds a templated constructor that is meant to be used with astd::tuple
. The contents of the tuple are copied to the underlying array storage using a meta-programAssign
, which simply iterates from N down to 0 at compile-time. Finally, themake_tuple_array
function accepts arbitrary number of parameters and constructs atuple_array
. The type of the first argument is assumed to be the element type of the array. Good compilers should eliminate the extra copy using RVO. The program works on g++ 4.4.4 and 4.6.1 with RVO.I think this question is really quite simple. You need a type that will be sized to the size of an
initializer_list
that it is initialized with.Try this:
Does this do any copying? In the most technical sense... yes. However, copying an initializer list specifically does not copy its contents. So this costs nothing more than a couple of pointer copies. Also, any C++ compiler worth using will elide this copy into nothing.
So there you have it: an array who's size is known (via
std::initializer_list::size
). The limitations here are:std::initializer_list
is pretty bare-bones. It doesn't even have operator[].The third is probably the most annoying. But it's also easily rectified:
There; problem solved. The initializer list constructor ensures that you can create one directly from an initializer list. And while the copy can no longer be elided, it's still just copying a pair of pointers.