Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #83869 > unrolled thread
| Started by | Juha Nieminen <nospam@thanks.invalid> |
|---|---|
| First post | 2022-04-29 07:56 +0000 |
| Last post | 2022-04-29 08:48 -0700 |
| Articles | 6 — 4 participants |
Back to article view | Back to comp.lang.c++
Uniform initialization ambiguity Juha Nieminen <nospam@thanks.invalid> - 2022-04-29 07:56 +0000
Re: Uniform initialization ambiguity Öö Tiib <ootiib@hot.ee> - 2022-04-29 06:29 -0700
Re: Uniform initialization ambiguity "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2022-04-29 19:30 +0200
Re: Uniform initialization ambiguity Juha Nieminen <nospam@thanks.invalid> - 2022-04-29 19:54 +0000
Re: Uniform initialization ambiguity Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-29 08:42 -0700
Re: Uniform initialization ambiguity Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-29 08:48 -0700
| From | Juha Nieminen <nospam@thanks.invalid> |
|---|---|
| Date | 2022-04-29 07:56 +0000 |
| Subject | Uniform initialization ambiguity |
| Message-ID | <t4g5no$raf$1@gioia.aioe.org> |
Suppose you have this overloaded function:
void foobar(const std::string&);
void foobar(const std::vector<int>&);
and you try to call it like:
foobar({});
you'll rather obviously get a compiler error because the call is ambiguous.
There's no way for the compiler to know which one you want to call.
However, if the functions were instead like this:
void foobar(const std::string&);
void foobar(int);
now that 'foobar({});' will compile just fine (at least with gcc), and
call the foobar(int) function. How so? Why is there no ambiguity here?
[toc] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2022-04-29 06:29 -0700 |
| Message-ID | <8307c4f9-8b63-49c4-a4a4-d089313df1efn@googlegroups.com> |
| In reply to | #83869 |
On Friday, 29 April 2022 at 10:56:59 UTC+3, Juha Nieminen wrote:
> Suppose you have this overloaded function:
>
> void foobar(const std::string&);
> void foobar(const std::vector<int>&);
>
> and you try to call it like:
>
> foobar({});
>
> you'll rather obviously get a compiler error because the call is ambiguous.
> There's no way for the compiler to know which one you want to call.
>
> However, if the functions were instead like this:
>
> void foobar(const std::string&);
> void foobar(int);
>
> now that 'foobar({});' will compile just fine (at least with gcc), and
> call the foobar(int) function. How so? Why is there no ambiguity here?
The initializer_list was IMHO worst thing of C++11 by large margin.
The identity conversion takes precedence over user-defined conversion.
Result can be confusing. Note that you get int version called also
with foobar({'a'}) silently.
If you do not want list used as argument then write an overload
dedicated to it:
void foobar(std::initializer_list<int>) { std::cout << "yuck!!!\n"; abort();}
If you want string overload chosen for initialiser_list passed then you
have to make int overload a template:
template<class Int, std::enable_if_t<std::is_same<Int, int>{}, int> = 0>
void foobar(Int t) {std::cout << "template int\n";}
But these are medicine that can be is worse than disease was; I do not
really know what to do.
[toc] | [prev] | [next] | [standalone]
| From | "Alf P. Steinbach" <alf.p.steinbach@gmail.com> |
|---|---|
| Date | 2022-04-29 19:30 +0200 |
| Message-ID | <t4h7ap$6uc$1@dont-email.me> |
| In reply to | #83878 |
On 29 Apr 2022 15:29, Öö Tiib wrote:
> void foobar(std::initializer_list<int>) { std::cout << "yuck!!!\n"; abort();}
I think you meant `= delete` for compile time detection, not a run time
error.
Probably a thinko (that's like a typo, brain on auto-pilot).
Cheers,
- Alf
[toc] | [prev] | [next] | [standalone]
| From | Juha Nieminen <nospam@thanks.invalid> |
|---|---|
| Date | 2022-04-29 19:54 +0000 |
| Message-ID | <t4hfpm$mkq$1@gioia.aioe.org> |
| In reply to | #83878 |
Öö Tiib <ootiib@hot.ee> wrote: > The initializer_list was IMHO worst thing of C++11 by large margin. You sure? I'd say that the uniform initialization causes more problems than initializer lists. Initializer lists are cool because you can initialize objects in the same way as you would a C style array, using a simple syntax. I see less use for uniform initialization, especially since its syntax gets messed up with initializer list syntax (even though semantically they are quite different things!) Sure, sometimes it saves you a bit of writing, but is it really worth it? Uniform initialization might be better if it used a syntax that's different from initializer lists and thus avoided ambiguity with them. (OTOH, I guess initializer lists *are* part of the concept of "uniform initialization", and that's the reason why both use the same syntax...)
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2022-04-29 08:42 -0700 |
| Message-ID | <t4h109$hal$1@dont-email.me> |
| In reply to | #83869 |
On 4/29/2022 12:56 AM, Juha Nieminen wrote:
> Suppose you have this overloaded function:
>
> void foobar(const std::string&);
> void foobar(const std::vector<int>&);
>
> and you try to call it like:
>
> foobar({});
>
> you'll rather obviously get a compiler error because the call is ambiguous.
> There's no way for the compiler to know which one you want to call.
>
> However, if the functions were instead like this:
>
> void foobar(const std::string&);
> void foobar(int);
>
> now that 'foobar({});' will compile just fine (at least with gcc), and
> call the foobar(int) function. How so? Why is there no ambiguity here?
Well, the rules for "List-initialization sequence [over.ics.list]" are
rather convoluted
http://eel.is/c++draft/over.ics.list
but one can figure out that the initialization of to `std::string` is
classified as "a user-defined conversion sequence"
http://eel.is/c++draft/over.ics.list#7.2
while initialization of an `int` is "an identity conversion"
http://eel.is/c++draft/over.ics.list#10.2
Obviously, the latter wins over the former.
--
Best regards,
Andrey Tarasevich
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2022-04-29 08:48 -0700 |
| Message-ID | <t4h1d3$ktg$1@dont-email.me> |
| In reply to | #83879 |
On 4/29/2022 8:42 AM, Andrey Tarasevich wrote:
> On 4/29/2022 12:56 AM, Juha Nieminen wrote:
>> Suppose you have this overloaded function:
>>
>> void foobar(const std::string&);
>> void foobar(const std::vector<int>&);
>>
>> and you try to call it like:
>>
>> foobar({});
>>
>> you'll rather obviously get a compiler error because the call is
>> ambiguous.
>> There's no way for the compiler to know which one you want to call.
>>
>> However, if the functions were instead like this:
>>
>> void foobar(const std::string&);
>> void foobar(int);
>>
>> now that 'foobar({});' will compile just fine (at least with gcc), and
>> call the foobar(int) function. How so? Why is there no ambiguity here?
>
> Well, the rules for "List-initialization sequence [over.ics.list]" are
> rather convoluted
>
> http://eel.is/c++draft/over.ics.list
>
> but one can figure out that the initialization of to `std::string` is
> classified as "a user-defined conversion sequence"
>
> http://eel.is/c++draft/over.ics.list#7.2
>
> while initialization of an `int` is "an identity conversion"
>
> http://eel.is/c++draft/over.ics.list#10.2
>
> Obviously, the latter wins over the former.
Since one of the parameters is a reference, I should probably also add a
link to
http://eel.is/c++draft/over.ics.list#9
which essentially boils down to applying the same rankings to the
initialization of the required temporary objects.
But you can remove the reference from your parameter declarations and
end up with an example that demonstrates the same decision process and
the same difference in rankings
void foobar(std::string);
void foobar(int);
...
foobar({}); // chooses `int`
So, the reference is really beside the point in this matter.
--
Best regards,
Andrey Tarasevich
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c++
csiph-web