Is void{} legal or not?
Asked Answered
P

3

31

This is a follow-up up of Differences between decltype(void()) and decltype(void{}).

In the comments and in the answer it is said more than once that void{} is neither a valid type-id nor a valid expression.

However, I came through [7.1.7.4.1/2] (placeholder type deduction) of the working draft, which says:

[...]

  • for a non-discarded return statement that occurs in a function declared with a return type that contains a placeholder type, T is the declared return type and e is the operand of the return statement. If the return statement has no operand, then e is void{};
    [...]

So, is void{} (conceptually) legal, or should the working draft use void()?

If it's acceptable as mentioned in the working draft (even though only as an - as if it's a - statement), it must be legal indeed. This means that decltype(void{}) should be valid as well, as an example.

Is there anything wrong with my reasoning? What exactly is the void{} mentioned in the bullet above and why is it a legal expression in this case?

Personalism answered 6/9, 2016 at 16:46 Comment(8)
Sounds like the standard is a little messed up here.Bibliofilm
I would (weakly) suspect a working draft error... Which is why it is a working draft and not a standard? :)Dennard
@Yakk: It's still a good idea to submit an issue on it, of course.Broadax
@NicolBolas If you are submitting an issue, please post here the link. Thanks. I would do that, but I don't even know how to do that!! :-)Personalism
@Yakk Well, it's quite uncommon for me to note an error in the working draft indeed!! :-)Personalism
@NicolBolas Meanwhile I sent an email to the discussion group. I'll be back with news if someone will reply.Personalism
This seems obvious enough to me that I just sent in github.com/cplusplus/draft/pull/917Hockenberry
@Hockenberry I'm not skilled enough to say obvious about an error in the working draft. :-)Personalism
P
9

Confirmed the bug. Already fixed.
Here is the discussion (pretty short to be honest).

So, the answer is - no, void{} is not legal.
It was a wording bug of the working draft.

Personalism answered 6/9, 2016 at 22:4 Comment(1)
This answer is now obsolete and the link is dead.Propinquity
B
12

To me it sounds like someone messed up merging the previous standard with the new one.

Previously the standard said this: (C++14 N4140, 7.1.6.4.7 [dcl.spec.auto]):

When a [...] return statement occurs in a function declared with a return type that contains a placeholder type, the deduced return type or variable type is determined from the type of its initializer. In the case of a return with no operand, the initializer is considered to be void().

The newer standard allows for if constexpr statements, so the language needed to change to reflect that. if constexpr leads to the concept of a potentially discarded return statement (if the return is in the not-taken branch of a constexpr if, then it's discarded and the return type is inferred from other return statements, if any).

Probably the new wording should be something like:

for a non-discarded return statement that occurs in a function declared with a return type that contains a placeholder type, T is the declared return type and e is the operand of the return statement. If the return statement has no operand, then T is auto and the deduced return type is void

Bibliofilm answered 6/9, 2016 at 18:35 Comment(7)
1. Type should be void(), neither void{} nor void. 2. You didn't reply actually to the question in the title: is void{} legal? No, it isn't. :-) 3. Not sure constexpr if is guilty for the error. Why did you say that? Thank you anyway for the detailed answer.Personalism
@skypjack: No, the type should not be void(). The wording currently says e is void{}, AndyG just talks about the type without ever trying to write an expression for e.Transcendence
N4296 is a C++17 draft. The C++14 text is N4140. The text you quoted differs between C++14 and N4296.Chainman
@Chainman that's good to know. I'm too cheap to get the real text, so I used the fallback isocpp recommends (N4296).Bibliofilm
N4140 is freely available, would be a good idea to revise your answer (either to use N4140's quote; or to not claim the quote is from C++14)Chainman
@BenVoigt Got it. Right. Thank you. Other questions still apply.Personalism
@M.M; Changed the answer to reflect N4140. Thanks for the heads-up. Hope all's good, mate.Bibliofilm
P
9

Confirmed the bug. Already fixed.
Here is the discussion (pretty short to be honest).

So, the answer is - no, void{} is not legal.
It was a wording bug of the working draft.

Personalism answered 6/9, 2016 at 22:4 Comment(1)
This answer is now obsolete and the link is dead.Propinquity
P
4

void{} is a valid expression

There is no difference between the expressions void() and void{} in modern C++. Both are legal. The current wording in [expr.type.conv] p2 states:

Otherwise, if the type is cv void and the initializer is () or {} (after pack expansion, if any), the expression is a prvalue of type void that performs no initialization.

void{} still isn't a valid type and T{} isn't a valid type in general. Braces aren't a valid way of constructing a declarator, and thus a type.

Historically, this wasn't always the case

Historically, there used to a be a difference, but CWG Issue 2351 void{} has made void{} valid as a defect report, meaning that it retroactively applies to C++11 and more recent standards.

The section in the working draft which you have quoted no longer exists in that form, and was just a temporary mistake. void{} was not valid back then and the author had made a mistake when using void{} as if it was valid.

Propinquity answered 22/9, 2023 at 21:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.