Why doesn't C++ allow implicit list initialization in the conditional operator? [duplicate]
Asked Answered
F

1

12

This code compiles:

std::string f(bool a, std::string const& b)
{
    if (a) return b;
    return {};
}

This code also compiles:

std::string f(bool a, std::string const& b)
{
    return a ? b : std::string{};
}

This code does not compile:

std::string f(bool a, std::string const& b)
{
    return a ? b : {};
}

Given that both result values of the ?: operator are required to be the same type, why doesn't it infer the type like it does in the first example?


It appears that this question might have a similar answer to this (which essentially boils down to "because nobody thought about it when writing the language specification"). However I still think it's useful to retain this question as the question itself is different, it's still sufficiently surprising, and the other wouldn't come up in searches for this issue.

Forepleasure answered 15/5, 2019 at 0:0 Comment(5)
Both types are required to be convertible to the same type. {} doesnt have a type.Geology
clang says {} is an initalizer list (which cannot be used here) live: godbolt.org/z/imYL6qAleron
Replacing {} with std::initializer_list<char>() also compiles.Benedix
Maybe this question could be turned into a language proposalLibelous
@miral: The correct term is "list initialization". That's what the standard calls it; you will find nothing in the standard about "uniform initialization".Indeed
Y
6

A braced initializer is not an expression and thus it has no type. See:

https://scottmeyers.blogspot.com/2014/03/if-braced-initializers-have-no-type-why.html

A braced initializer is a grammatical construct with special rules in the standard, explicitly specifying allowed use and type deduction. These special rules are needed exactly because braced initializers have no type. Using them in ?: statements is not specified, and thus the program is ill-formed.

If you really need to hear the man himself say it three times in a row before you believe it, then:

https://youtu.be/wQxj20X-tIU?t=1792

Yseulte answered 15/5, 2019 at 1:4 Comment(13)
but return {}; worksDunsany
@Dunsany With return {} the return type of the function is known.Yseulte
with return a ? b : {}; the return type of the function isn't known?Dunsany
@Dunsany The return type is known, but the type of the ?: isn't known.Yseulte
return a ? b : ""; compiles, as does return a ? b : std::initializer_list<char>{};. So clearly the compiler is allowed to perform construction/conversion based on the declared return type and/or the type of b. So {} should be equally valid.Forepleasure
@Forepleasure "" has a type. std::initializer_list<char>{} also has a type. {} doesn't.Yseulte
Correct, but that means it's compatible with any type, which is how it works in return statements, arguments, and initialisation to begin with.Forepleasure
@Miral: "it's compatible with any type" No, it isn't. It is a grammatical construct which, in certain locations, can be used to initialize a prvalue of a type. It isn't "compatible" with anything.Indeed
@Forepleasure That's because the standard specifically allows for that. Braced initializers have no type, and thus their allowed use needs to be explicitly specified by the standard. Using it in ?: was never specified and so the program is ill-formed.Yseulte
@NikosC.: It should be noted that braced-init-lists do not have a type because they're not expressions. They are a distinct grammatical construct from expressions. So asking them about type is like asking them about their "value" or any other thing associated with expressions.Indeed
@Dunsany the language specification for the return statement explicitly says that the next thing can either be an expression, or a braced list, and goes on to define what will happen if a braced list is provided (namely, that the braced list is taken as initializer for copy-initialization of the result object)Libelous
I get that it's not a compiler error. But the other way to interpret the question is "does it actually make sense as a requirement?" or "is there a technical reason it cannot be done?"Dunsany
As moderator stated "It appears that this question might have a similar answer to this (which essentially boils down to "because nobody thought about it when writing the language specification")." I don't see how it's duplicate. Nor I don't see reason it can't be done as type can be guessed from one of operands.Minelayer

© 2022 - 2024 — McMap. All rights reserved.