Date: Thu, 28 Nov 2024 22:28:30 +0100
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 ?
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 ?
Received on 2024-11-28 21:28:44