Open xmh0511 opened 3 years ago
The first issue might be interpreted by the following rule:
In all contexts, a declarator is interpreted as given below. Where an abstract-declarator can be used (or omitted) in place of a declarator ([dcl.fct], [except.pre]), it is as if a unique identifier were included in the appropriate place ([dcl.name]).
That means MSVC has a wrong implementation. The second issue still remains no explanation.
First, this is not the place to file core issues, even if Jens is often kind enough to relay them.
Considering that
auto f(int) -> int;
auto (*p)(int a) -> decltype(a) = f;
is accepted by all of the usual suspects but that
template<class T> int g(std::remove_pointer_t<T>);
int (*q)(int a) = g<decltype(a)>;
is just as universally rejected, we evidently need a new rule for non-function declarations that doesn't use init-declarator as the extent. You're right about the case of a function returning a function pointer, but we need to figure out what the rule should be for non-function declarations before we try to fix the "function but not the outermost function declarator" case.
First, this is not the place to file core issues, even if Jens is often kind enough to relay them.
Considering that
auto f(int) -> int; auto (*p)(int a) -> decltype(a) = f;
is accepted by all of the usual suspects but that
template<class T> int g(std::remove_pointer_t<T>); int (*q)(int a) = g<decltype(a)>;
is just as universally rejected, we evidently need a new rule for non-function declarations that doesn't use init-declarator as the extent. You're right about the case of a function returning a function pointer, but we need to figure out what the rule should be for non-function declarations before we try to fix the "function but not the outermost function declarator" case.
@jensmaurer Thanks. @opensdh I just don't find an high efficiently channel to discuss these issues except here. Back to the issue itself, if the behavior of these implementations is correct, we might need to define the rule for concept what is P
associated with a declarator(which declarator is it?), it might be:
P is associated with a declarator of which a parameters-and-qualifiers is a direct component and the parameters-and-qualifiers directly enclose the P, and the declarator has the form noptr-declarator parameters-and-qualifiers trailing-return-type or noptr-declarator parameters-and-qualifiers.P is associated with a component if P is firstly introduced by the component (i.e, P is the direct component of that component on grammar).If P is associated with a declarator, its scope extends to the end of the declarator, or function-definition of which the declarator declares a function.
Example:
auto(* ptr(double a))(int b)->decltype(b); //ok auto D(int b)-> decltype(b), b extends to the end of the declarator
auto(* fun(double a))(int b)->int{
a = 1; //ok fun(double a) declares a function, a can be named here
b = 0; //error auto (* D)(int b)->int, since `(* D)(int b)->int` does not declare a function
return nullptr;
}
Please see this example:
It's obviously P is not associated with any declarator instead with abstract-declarator, let alone whether it is preceded by noptr-declarator of the form declarator-id attribute-specifier-seq opt. In this example, the name of the parameter is used in the place that has exceeded the scope of the function parameter scope introduced by P. However, the case is valid in any major implementation other than MSVC. The other bullets are irrelevant with this case. So, it seems the function parameter scope is underspecified for this case.
Issue 2:
First of all, this case is rejected by all major implementations. Assume the parameter-declaration-clause that comprises the parameter declaration
double a
is called P1, the other(comprisesint b
) is called P2. As shown in the Figure, P1 is associated with the declarator of the complete declaration and is preceded by noptr-declarator of the form declarator-id attribute-specifier-seq opt that isptr
. In terms of the first bullet in the above, the scope should be extended to the nearest enclosing init-declarator(* ptr(double a))(int b)->decltype(a)
since the other cases(member-declarator...) are all not suitable here. Hence, the use of the identifiera
withindecltype
should be valid. But this conclusion is denied by implementations.