(This question has been broken out from the discussion to this answer, which highlights CWG 1892)
Some paragraphs of the standard applies specific rules to function declarators; e.g. [dcl.spec.auto]/3 regarding placeholder types [emphasis mine]:
The placeholder type can appear with a function declarator in the decl-specifier-seq, type-specifier-seq, conversion-function-id, or trailing-return-type, in any context where such a declarator is valid. If the function declarator includes a trailing-return-type ([dcl.fct]), that trailing-return-type specifies the declared return type of the function. Otherwise, the function declarator shall declare a function. [...]
restricts where placeholder types may appear with(in) a function declarator. We may study the following example:
int f() { return 0; }
auto (*g)() = f; // #1
which both GCC and Clang accepts, deducing g
to int(*)()
.
- Is a pointer to function (sometimes/always?) a function declarator?
- Or, alternatively, applied to the example, should
#1
be rejected as per [dcl.spec.auto]/3, or does the latter not apply here as a pointer to function is not a function declarator (instead allowing#1
as per [dcl.spec.auto]/4 regarding variable type deduction from initializer)?
The rules for what is a given declarator is not entirely easy to follow, but we may note that, from [dcl.decl]/1
A declarator declares a single variable, function, or type, within a declaration.
that a given declarator is either any of a variable declarator, a function declarator or a type declarator.
- [dcl.ptr] covers (variable) declarators that are pointers, but does not explicitly (/normatively) mention pointers to functions, albeit does so non-normatively in [dcl.ptr]/4
- [dcl.fct] covers function declarators but does not mention function pointers as part of function declarations, other than a note that function types are checked during assignment/initialization to function pointers (which is not relevant for what a function declarator is)
My interpretation is that #1
is legal (as per the current standard), as it falls under a variable declarator. If this is actually correct, then the extended question (from the linked thread) is whether
template<auto (*g)()>
int f() { return g(); }
is legal or not (/intended to be legal or not as per CWG 1892); as the template parameter arguably contains a declarator that is a function pointer declarator, and not a function declarator.
We may finally note, as similarly pointed out in the linked to answer, that
template<auto g()> // #2
int f() { return g(); }
is arguably ill-formed (although this example is also accepted by both GCC and Clang), as the non-type template parameter at #2
is a function declarator and is thus used in an illegal context as per [dcl.spec.auto]/3, as it does not contain a trailing return type and does not declare a function.
auto (*g)() = f;
works for the same reasonauto x = 42;
works, not because it has something to do with functions. In fact, one can writeauto x = 42, (*g)() = f;
– Raverauto (*g)() = f
being well-formed, the key being that there is no function declarator involved in its declaration (such that [dcl.spec.auto]/3 does not apply). Your second example is [dcl.decl]/3 and is not significant here; whether the single declarator being discussed is well-formed or ill-formed (in isolation or as part of a decl. with several declarators). – Bettermentauto (*g)()
is parsed then? – Reign#1
is ill-formed?). – Bettermentauto (*g)()
without [dcl.fct].auto (*g)()
has formT D1()
. – Reignfunction declarator
is vague here.There's no formal definition forfunction declarator
. Does it mean the declarator declares a function or the declarator has the form D1(parameter-declaration-clause )cv-qualifier-seq<opt> ref-qualifier <opt> noexcept-specifier<opt> attribute-specifier-seq<opt>?It appears to me that "A declarator declares a single variable, function, or type, within a declaration." seems to refer to the former. However,auto (*g)()
does not declare a function as per function – Invitationint* fun()
, It first matches the form of a pointer,T D
where D has the form* attribute-specifier-seq<opt> cv-qualifier-seq <opt> D1
, Can it be calledpointer declarator
? I don't think. Instead, the declarator indeed declares a function here. – Invitation