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


Groups > comp.lang.c++ > #83869 > unrolled thread

Uniform initialization ambiguity

Started byJuha Nieminen <nospam@thanks.invalid>
First post2022-04-29 07:56 +0000
Last post2022-04-29 08:48 -0700
Articles 6 — 4 participants

Back to article view | Back to comp.lang.c++


Contents

  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

#83869 — Uniform initialization ambiguity

FromJuha Nieminen <nospam@thanks.invalid>
Date2022-04-29 07:56 +0000
SubjectUniform 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]


#83878

FromÖö Tiib <ootiib@hot.ee>
Date2022-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]


#83881

From"Alf P. Steinbach" <alf.p.steinbach@gmail.com>
Date2022-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]


#83883

FromJuha Nieminen <nospam@thanks.invalid>
Date2022-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]


#83879

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2022-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]


#83880

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2022-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