Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #69986
| From | Bo Persson <bo@bo-persson.se> |
|---|---|
| Newsgroups | comp.lang.c++ |
| Subject | Re: Initialization of std::vector<std::string> throws |
| Date | 2019-11-22 16:22 +0100 |
| Message-ID | <h3qcpoF446jU1@mid.individual.net> (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> |
On 2019-11-22 at 16:03, Ralf Goertz wrote:
> 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.
>
> By the way my original question was why a double brace initializer list
> doesn't work for
>
> std::vector<std::string> pt({{"1","2"}});
>
> (it compiles but throws a std::length_error because the arguments are
> taken as pointers) but works perfectly for
>
> std::vector<int> pt({{1,2}});
>
> On the other hand
>
> std::vector<std::string> pt({{"1","2","3"}});
>
> again works as expected (with or without the parenthesis) which I just
> figured out. So the two string element case fails only because the
> compiler picks the wrong constructor. I find that odd because the
> initializer list seems to be the more obvious choice…
>
It is not *that* obvious to the compiler, as it tries to match an
initializer_list<char> and you supply two char*. Unfortunately that is a
better match for std::string(iterator, iterator), but then of course
fails at runtime as it is not a valid iterator pair.
For *any* number of strings other than 2, the std::string(iterator,
iterator) will immediately be ruled out, so works much better.
You would have a better chance to match the vector's initializer_list
constructor if you actually provided som std::string literals:
std::vector<std::string> pt({{"1"s,"2"s}});
Bo Persson
Back to comp.lang.c++ | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll 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