Current standard draft, in [dcl.type.auto.deduct], Part 3, reads:

If the placeholder-type-specifier is of the form type-constraint(opt) auto, the deduced type T′ replacing T is determined using the rules for template argument deduction. If the initialization is copy-list-initialization, a declaration of std::initializer_list shall precede ([basic.lookup.general]) the placeholder-type-specifier. Obtain P from T by replacing the occurrences of type-constraint(opt) auto either with a new invented type template parameter U or, if the initialization is copy-list-initialization, with std::initializer_list<U>. Deduce a value for U using the rules of template argument deduction from a function call ([temp.deduct.call]), where P is a function template parameter type and the corresponding argument is E. If the deduction fails, the declaration is ill-formed. Otherwise, T′ is obtained by substituting the deduced U into P.

The only example I can see with "multiple occurrences" of (optionally type-constrained) auto within type T, is with a function where auto is in both decl-specifier and trailing-return-type:

auto foo() -> auto;

or similarly, for a variable or function parameter that have function pointer/reference type, e.g.;

auto (*fp)() -> auto = ...initializer...;

I see two chances here:

1) preliminary Part 2 clarifies that the type T to be considered is, for example, the declared return type of a function, or the declared type of a variable. In former case, it means that a single auto is considered, because [dcl.spec.auto.general] indicates the trailing-return-type replaces the type of the decl-specifier, and this is true even for latter case despite [dcl.spec.auto.general]-p5 does not define an explicit (overall) declared type for the variable.

In this perspective 1), T would anyway contain a single 'auto' and the wording "occurrences" should be fixed, for example from "the occurrences of type-constraint(opt) auto" to "the placeholder-type-specifier" (provided that the begin of p3 states the placeholder is just a single type-constraint(opt) auto").


2) if, for any other reason, T really contains both 'auto', then the wording of replacing U in P with the deduced type is formally wrong, as for example for the function above foo(), if the type parameter U is deduced as int, then the replacement leads to:

int foo() -> int;

which is syntactically not allowed.

Additionally, even with a single auto, in decl-specifier only:

auto (*fp)() -> int = ...initializer...;

Therefore, even with perspective 2), the wording about replacing should change.


Are there other intended examples with 'multiple occurrences' ? I tried to ask on stackoverflow but no one provided any.



As an additional note, [dcl.spec.auto.general]-p4 states that a deduction is done in ase any non-discarded return statement is present, and even [dcl.type.auto.deduct]-p2 focuses on the non-discarded return statements.

Shouldn't we extend [dcl.spec.auto.general]-p4 for deducing void type when no non-discarded return statement is present ?