Date: Mon, 7 Dec 2020 12:18:11 +0000
Consider
```
typedef int a1, a2, a3;
typedef char a4;
namespace ns {
class A {
typedef A(a1); // #1
friend A(a2)(); // #2
static A(a3); // #3
explicit A(a4); // #4
};
}
```
Clang rejects #1, complaining that "typedef name must be an identifier", while MSVC, GCC, ICC accept it.
GCC and ICC seem to treat #1 as a valid declaration with redundant parentheses (i.e. equivalent to `typedef A a1;`).
MSVC seems to ignore `typedef` and treat #1 as a valid declaration of constructor whose parameter type is `a1` (i.e. equivalent to `A(a1);`).
Clang, MSVC, and GCC reject #2 (complaining that "function cannot return function type"), while ICC seems to consider it equivalent to `friend A a2();`.
All compilers reject #3, complaining that "constructor cannot be declared 'static'".
Everyone agrees that #4 is a valid constructor declaration.
I can't find anything in the standard that specifies this behavior. I only found [dcl.spec.general]/3 <http://eel.is/c++draft/dcl.spec.general#3.sentence-1>:
> If a _type-name_ is encountered while parsing a _decl-specifier-seq_, it is interpreted as part of the _decl-specifier-seq_ if and only if there is no previous _defining-type-specifier_ other than a _cv-qualifier_ in the _decl-specifier-seq_.
This seems to suggest that in all these declarations, `A` should be considered to be the type of the entity being declared, instead of the constructor name, which does not match reality.
I believe that the standard should clarify how these declarations should be interpreted. In particular, it needs to specify when the name of the current class (the "injected-class-name") is considered to name a constructor in declarations like these.
Received on 2020-12-07 06:18:15