28

This is a follow-up up of this question.
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.

That was fine, it made sense and that was all.

Then I came through [7.1.7.4.1/2] (placeholder type deduction) of the working draft.
There it is said that:

[...]
- 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 not?
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.
Otherwise, should the working draft use void() instead of void{}?


Well, to be honest, I'm quite sure I'm not skilled enough to point out an error in the working draft, so the real question is: what 's wrong in my reasoning?
What's exactly the void{} mentioned in the bullet above and why it's a legal expression in this case?

Community
  • 1
  • 1
skypjack
  • 49,335
  • 19
  • 95
  • 187

2 Answers2

11

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

AndyG
  • 39,700
  • 8
  • 109
  • 143
  • 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. – skypjack Sep 06 '16 at 22:06
  • 1
    @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`. – Ben Voigt Sep 06 '16 at 22:13
  • N4296 is a C++17 draft. The C++14 text is N4140. The text you quoted differs between C++14 and N4296. – M.M Sep 06 '16 at 23:14
  • @M.M that's good to know. I'm too cheap to get the real text, so I used the fallback isocpp recommends (N4296). – AndyG Sep 07 '16 at 02:20
  • 1
    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) – M.M Sep 07 '16 at 03:58
  • @BenVoigt Got it. Right. Thank you. Other questions still apply. – skypjack Sep 07 '16 at 07:12
  • @M.M; Changed the answer to reflect N4140. Thanks for the heads-up. Hope all's good, mate. – AndyG Sep 07 '16 at 14:45
10

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.

skypjack
  • 49,335
  • 19
  • 95
  • 187