Re: Type of initializer lists ( N2215 feedback)
On Mar 26, 7:36 am, "Vidar Hasfjord" <vattilah-gro...@yahoo.co.uk>
wrote:
I regularly read the latest papers and proposals for C++09 with great
interest, and I commend everyone who is contributing so much time and
hard work to improve the language. One of the new features I welcome
from a language usability perspective is the generalization of
initializer lists (N2215).
That said, the current proposed solution seems less than optimally
orthogonal.
I hadn't read it before, but now that I've done it looks rather bad.
I was expecting something more along the lines of
boost::mpl::vector_c, but since C99-like initialization is wanted and
not just initialization from constant expressions, that's impossible.
So the solution given in the paper is just to make the
initializer_list a container of values (that isn't even heterogenous
it seems) and traverse it at runtime.
Not really an efficient solution. Actually using an initializer_list
to initialize an array would be way less efficient that initialize it
with regular initialization lists, because lots of copies would be
needed.
The standard C++ library already has too much useless copies, I'm not
sure of the worth to add even more.
But actually, is a value really what initializes things? I would
rather say that an initializer is a function that indicates how to
construct the objects.
As a result, wouldn't it be better to actually to make those
initializer_lists into a list of functors? Thanks to that,
construction will be delayed, there will be no useless copy, since
creating the objects will be delegated to the object actually using
the initializer_list to initialize itself.
Thanks to inlining technology, it would be as efficient as the real
thing, in-place construction.
For example, here is what it could actually do :
struct Foo
{
Foo() {}
Foo(int) {}
};
int i = 7;
std::vector<Foo> foo = { 3, Foo(i), Foo() };
would be transformed to
struct lambda_1
{
typedef int type;
void operator()(void* p)
{
new(p) int(3);
}
};
struct lambda_2
{
typedef Foo type;
lambda_2(int&& a) : a_(a) {}
void operator()(void* p)
{
new(p) Foo(a_);
}
private:
a&& a_;
};
struct lambda_3
{
typedef Foo type;
void operator()(void* p)
{
new(p) Foo();
}
};
std::vector<Foo> foo(std::make_tuple(lambda_1(), lambda_2(i),
lambda_3()));
Of course, the constructor to initializes from that kind of stuff
becomes quite less trivial than with iterators, but it happens at
compile-time, there is no copy, and the initializer-list can be
heterogenous. It allows the same kind of thing as regular C99
initialization lists, except that /we/ choose what to do with the
list.
Here, depending on whether lambda_x::type is Foo, we either directly
call the the functor on the memory or we create a temporary of type
lambda_x::type, initialize it with the functor, and construct a Foo in
memory with it.
---
[ 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://www.comeaucomputing.com/csc/faq.html ]