Consider
using foo = int;
struct A {
typedef A (foo)();
};
GCC and ICC accept the snippet, while Clang and MSVC reject it. Clang's error message is
<source>:4:15: error: function cannot return function type 'void ()' typedef A (foo)(); ^ <source>:4:13: error: typedef name must be an identifier typedef A (foo)(); ^ 2 errors generated.
And MSVC says
<source>(4,15): error C2091: function returns function typedef A (foo)(); ^
(live demo)
Why do Clang and MSVC produce this error? Which compilers are correct?
(I'm specifically looking for quotation from the standard or any defect report.)
Both Clang and MSVC are ignoring the typedef
specifier and reading the declaration as that of a constructor (that is, A
is the constructor name) accepting parameter types (foo)
(that is, (int)
) and "returning" a function type signified by the trailing parentheses ()
.
Yes, constructors don't have return types; but if they did have return types they would have return type A
, so the additional ()
at the end makes these compilers think that you now have a constructor with return type the function type A()
.
This is supported by noting that the following "similar" declarations have similar error messages:
A (foo)();
typedef ~A(foo)();
Also, by adding static
we can get an illuminating error message from MSVC:
A static (int)();
error C2574: '(__cdecl *A::A(int))(void)': cannot be declared static
For workarounds: under Clang (but not MSVC) you can move the typedef
specifier to the right, or use an elaborated type specifier:
A typedef (foo)();
typedef struct A (foo)();
Under all compilers you can remove or add parentheses:
typedef A foo();
typedef A ((foo))();
And you can always update to a type alias:
using foo = A();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With