This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 113d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-03-20


1877. Return type deduction from return with no operand

Section: 9.2.9.7  [dcl.spec.auto]     Status: CD4     Submitter: Daveed Vandevoorde     Date: 2014-02-20

[Moved to DR at the November, 2014 meeting.]

Return type deduction from a return statement with no expression is described in 9.2.9.7 [dcl.spec.auto] paragraph 7 as follows:

When a variable declared using a placeholder type is initialized, or 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(). Let T be the declared type of the variable or return type of the function. If the placeholder is the auto type-specifier, the deduced type is determined using the rules for template argument deduction. If the deduction is for a return statement and the initializer is a braced-init-list (9.4.5 [dcl.init.list]), the program is ill-formed. Otherwise, obtain P from T by replacing the occurrences of auto with either a new invented type template parameter U or, if the initializer is a braced-init-list, with std::initializer_list<U>. Deduce a value for U using the rules of template argument deduction from a function call (13.10.3.2 [temp.deduct.call]), where P is a function template parameter type and the initializer is the corresponding argument.

However, this does not work: the deduction for an argument of void() would give a parameter type of void and be ill-formed. It would be better simply to say that the deduced type in this case is void.

In a related example, consider

  decltype(auto) f(void *p) {
    return *p;
  }

This is presumably an error because decltype(*p) would be void&, which is ill-formed. Perhaps this case should be mentioned explicitly.

Notes from the June, 2014 meeting:

The last part of the issue is not a defect, because the unary * operator requires its operand to be a pointer to an object or function type, and void is neither, so the expression is ill-formed and deduction does not occur for that case.

It was also observed during the discussion that the same deduction problem occurs when returning an expression of type void as when the expression is omitted, so the resolution should cover both cases.

Proposed resolution (June, 2014):

Change 9.2.9.7 [dcl.spec.auto] paragraph 7 as follows:

When a variable declared using a placeholder type is initialized, or 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 or with an operand of type void, the initializer declared return type shall be auto and the deduced return type is void considered to be void(). Let Otherwise, let T be the declared type...