Path: csiph.com!eternal-september.org!feeder.eternal-september.org!reader01.eternal-september.org!.POSTED!not-for-mail
From: Tim Rentsch
Newsgroups: comp.lang.c++
Subject: Re: Initialization of std::vector throws
Date: Thu, 28 Nov 2019 13:44:37 -0800
Organization: A noiseless patient Spider
Lines: 78
Message-ID: <86h82nad6i.fsf@linuxsc.com>
References: <20191122134409.33dffbcff5234841f8ea7411@cvine--nospam--.freeserve.co.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: reader02.eternal-september.org; posting-host="dce185ee50ea005ee4a34884a21fb89a"; logging-data="29801"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18MrJfl+8Y3FaGRXh4132Hao2s2055nyJk="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:EWE44p/pq4KwrhWhoOCK8xyfvSg= sha1:m5qanxE+btdIq773X5EUeWTVaJo=
Xref: csiph.com comp.lang.c++:70095
Ralf Goertz writes:
> Am Fri, 22 Nov 2019 13:44:09 +0000
> schrieb Chris Vine :
>
>> On Fri, 22 Nov 2019 12:12:43 +0100
>> Ralf Goertz wrote:
>>
>>> Since nobody has explained that satisfactorily yet (also see Tim's
>>> answer to Pavel) and I just stumbled over it again, I'd like to
>>> follow up. In the following situation double braces are necessary.
>>> But why? This kind of problem led to my original belief that for
>>> containers they were always needed.
>>>
>>> #include
>>> #include
>>>
>>> struct Foo {
>>> std::vector v;
>>> Foo(std::vector v_=std::vector()) : v(v_){}
>>> };
>>>
>>> int main() {
>>> Foo f{{4,5}}; //double braces needed
>>> for (auto r:f.v)
>>> std::cout<>> return 0;
>>> }
>>>
>>>
>>> With single braces I get:
>>> problem.cc: In function ?int main()?:
>>> problem.cc:10:14: error: no matching function for call to
>>> ?Foo::Foo()? 10 | Foo f{4,5};
>>> | ^
>>> problem.cc:6:14: note: candidate: ?Foo::Foo(std::vector)?
>>> 6 | Foo(std::vector v_=std::vector()) : v(v_){}
>>> | ^~~
>>> problem.cc:6:14: note: candidate expects 1 argument, 2 provided
>>> problem.cc:4:8: note: candidate: ?Foo::Foo(const Foo&)?
>>> 4 | struct Foo {
>>> | ^~~
>>> problem.cc:4:8: note: candidate expects 1 argument, 2 provided
>>> problem.cc:4:8: note: candidate: ?Foo::Foo(Foo&&)?
>>> problem.cc:4:8: note: candidate expects 1 argument, 2 provided
>>
>> I do not have all the previous exchanges available so I may be
>> repeating what others have said, but the reason why single braces fail
>> is because you are passing two arguments to a conversion constructor
>> of Foo taking one (or no) argument. As to why double braces work, my
>> guess is that (ignoring elision) the inner braces perform an implicit
>> conversion to std::vector via std::vector's constructor taking an
>> initializer_list, constructing a temporary vector with two elements in
>> the vector, and that this then initializes Foo, using std::vector's
>> move constructor.
>
> Okay I guessed that much, but why can't the compiler do the latter when
> there is only one pair of braces? The error message clearly indicates
> that an initializer list is considered.
I don't have anything to add about why this example behaves as it
does, but I have two related comments. One, it doesn't surprise
me at all that two pairs are braces are needed. Two, I'm not
sure having it work with only one pair of braces is a good idea;
if anything I suspect it would be more confusing than helpful.
My analogy is initializing structs (for C, I don't know if C++
might have changed here): I know there are rules for omitting
braces in some cases when initializing structs with nested arrays
or nested structs, but it seems insane to take advantage of those
rules. Presumably they were put in for compatibility with early
C code, which makes sense, but not continuing to use them going
forward. Returning to the C++ example, having two pairs of
braces matches my understanding of what's going on; allowing
only one pair of braces to do the same thing would mean I have
to create a more elaborate and more complicated mental model to
understand what the program is doing and how the language works.
I would much rather not to have to create these more elaborate
models. Do you see what I mean?