Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do Clang and MSVC not like a member typedef declaration with a redundant set of parentheses?

Tags:

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.)

like image 481
cpplearner Avatar asked Dec 05 '20 13:12

cpplearner


1 Answers

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();
like image 56
ecatmur Avatar answered Oct 17 '22 22:10

ecatmur