Google 网上论坛不再支持新的 Usenet 帖子或订阅项。历史内容仍可供查看。

Uniform initialization ambiguity

已查看 27 次
跳至第一个未读帖子

Juha Nieminen

未读,
2022年4月29日 03:56:592022/4/29
收件人
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?

Öö Tiib

未读,
2022年4月29日 09:29:322022/4/29
收件人
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.

Andrey Tarasevich

未读,
2022年4月29日 11:42:182022/4/29
收件人
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

Andrey Tarasevich

未读,
2022年4月29日 11:49:062022/4/29
收件人
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.

Alf P. Steinbach

未读,
2022年4月29日 13:30:192022/4/29
收件人
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

Juha Nieminen

未读,
2022年4月29日 15:54:492022/4/29
收件人
Öö Tiib <oot...@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...)
0 个新帖子