Boost logo

Boost :

Subject: Re: [boost] [preprocessor] Warning: Incoming
From: John Bytheway (jbytheway+boost_at_[hidden])
Date: 2011-07-02 06:00:39


On 02/07/11 10:25, Mathias Gaunard wrote:
> On 07/02/2011 01:55 AM, Paul Mensonides wrote:
>> On Sat, 02 Jul 2011 01:07:04 +0200, Mathias Gaunard wrote:
>>
>>> On 07/02/2011 12:44 AM, Paul Mensonides wrote:
>>>> (I
>>>> do believe, however, that std::initializer_list<T> is a
>>>> misfeature. I
>>>> personally think the { a, b, c } should have been mapped onto a
>>>> constructor call taking a, b, and c--which may or may not use variadic
>>>> templates).
>>>
>>> Both are possible in C++0x.
>>> That's how you initialize tuples.
>>
>> The { a, b, c } syntax does not map onto constructors.
>
> Yes it does.
> {} has been unified to be the same as constructors in C++0x.
>
> You can do
> tuple<int, double> t {1, 2.};
> but unforunately you cannot do
> tuple<int, double> t = {1, 2.};
> because tuple::tuple(int&&, double&&) is explicit (arguably a bug, it
> should only be explicit in the unary case).
>
> Both cases work with pair<int, double> (which is very important when you
> want to initialize maps).
>
>
>> It maps onto
>> std::initializer_list<T> for some particular (and unique) T.
>
> There are special overloading resolution rules for initializer_list that
> allows the two.
>
> But then I've already said this. If you don't want to believe me, I
> invite you to take a look at the working draft for C++0x standard at
> section 8.5.4.

I've just been reading the standard and playing around with gcc 4.5.2,
and I have to say the results are a bit confusing.

    class A {};

    typedef std::vector<int> V;
    V v1{size_t(10)}; // vector of size 1
    V v2{size_t(10), 10}; // vector of size 2
    V v3(size_t(10), 10); // vector of size 10
    V v4{10, 10}; // vector of size 2

    typedef std::vector<A> VA;
    VA va1{size_t(10)}; // vector of size 10
    //VA va2{size_t(10), A()}; // compile error
    VA va3(size_t(10), A()); // vector of size 10
    VA va4{A(), A()}; // vector of size 2

Two things in particular surprise me:

1. That the construction of va2 is a compile error. I feel that the
elements of the initializer lists being of different types should
prevent the consideration of initializer-list constructors and fall back
to normal constructors.

2. That the construction of v1 prefers V(initializer_list<int>) over
V(size_t).

I think the crux of the problem is the section [over.match.list] in
N3290, where it says:

"Initially, the candidate functions are the initializer-list
constructors (8.5.4) of the class T and the argument list consists of
the initializer list as a single argument."

but I can't find described there or in [dcl.init.list] (8.5.4) under
what circumstances initializer list constructors are discarded without
error due to the elements not being of the right type. It clearly
happens sometimes (else the construction of va1 would be an error) but
not always (else the construction of va2 would not be an error). Can
anyone point me to the relevant text?

John Bytheway


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk