Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #70095

Re: Initialization of std::vector<std::string> throws

From Tim Rentsch <tr.17687@z991.linuxsc.com>
Newsgroups comp.lang.c++
Subject Re: Initialization of std::vector<std::string> throws
Date 2019-11-28 13:44 -0800
Organization A noiseless patient Spider
Message-ID <86h82nad6i.fsf@linuxsc.com> (permalink)
References (1 earlier) <cone.1567599651.572642.18978.1004@monster.email-scan.com> <qkoav3$97d$2@dont-email.me> <qr8frb$47q$1@dont-email.me> <20191122134409.33dffbcff5234841f8ea7411@cvine--nospam--.freeserve.co.uk> <qr8tbg$qem$1@dont-email.me>

Show all headers | View raw


Ralf Goertz <me@myprovider.invalid> writes:

> Am Fri, 22 Nov 2019 13:44:09 +0000
> schrieb Chris Vine <chris@cvine--nospam--.freeserve.co.uk>:
>
>> On Fri, 22 Nov 2019 12:12:43 +0100
>> Ralf Goertz <me@myprovider.invalid> 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 <vector>
>>> #include <iostream>
>>>
>>> struct Foo {
>>>     std::vector<int> v;
>>>     Foo(std::vector<int> v_=std::vector<int>()) : v(v_){}
>>> };
>>>
>>> int main() {
>>>     Foo f{{4,5}};  //double braces needed
>>>     for (auto r:f.v)
>>>         std::cout<<r<<std::endl;
>>>     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(<brace-enclosed initializer list>)? 10 |     Foo f{4,5};
>>>       |              ^
>>> problem.cc:6:14: note:  candidate: ?Foo::Foo(std::vector<int>)?
>>>     6 |     Foo(std::vector<int> v_=std::vector<int>()) : 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<int> 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?

Back to comp.lang.c++ | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

Initialization of std::vector<std::string> throws Ralf Goertz <me@myprovider.invalid> - 2019-09-04 14:09 +0200
  Re: Initialization of std::vector<std::string> throws Sam <sam@email-scan.com> - 2019-09-04 08:20 -0400
    Re: Initialization of std::vector<std::string> throws Ralf Goertz <me@myprovider.invalid> - 2019-09-04 14:33 +0200
      Re: Initialization of std::vector<std::string> throws Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2019-09-05 23:26 -0400
        Re: Initialization of std::vector<std::string> throws Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-09-18 08:37 -0700
      Re: Initialization of std::vector<std::string> throws Ralf Goertz <me@myprovider.invalid> - 2019-11-22 12:12 +0100
        Re: Initialization of std::vector<std::string> throws Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2019-11-22 13:44 +0000
          Re: Initialization of std::vector<std::string> throws Ralf Goertz <me@myprovider.invalid> - 2019-11-22 16:03 +0100
            Re: Initialization of std::vector<std::string> throws Bo Persson <bo@bo-persson.se> - 2019-11-22 16:22 +0100
            Re: Initialization of std::vector<std::string> throws Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2019-11-22 16:13 +0000
            Re: Initialization of std::vector<std::string> throws Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-28 13:44 -0800
    Re: Initialization of std::vector<std::string> throws "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2019-11-22 16:30 +0100
  Re: Initialization of std::vector<std::string> throws Bonita Montero <Bonita.Montero@gmail.com> - 2019-09-04 14:43 +0200

csiph-web