Werner Erasmus Werner Erasmus - 7 months ago 39
C++ Question

override specifier as template parameter - is it valid?

I have the following piece of code that does not compile under Visual C++ 2015, but does under GCC 4.8.4. I'm wondering which is right? The code in question is here below:

template <class T> class ATemplate;
template <class R, class A1>
struct ATemplate<R(A1)>{ };

int main()
ATemplate<void(int)> x;
// ATemplate<void(int)override> y; //---Does not compile!!!
return 0;

Is it wrong to use override as specifier here below (or const). Similar code exists in the GMock library, where macro expansion is used to generate the template parameter (including override), as well as the actual function signature.

Visual C++ 2015 produces the following error when removing the commented out line:

x.cpp(11): error C2062: type 'int' unexpected
x.cpp(11): error C2976: 'ATemplate': too few template arguments
x.cpp(4): note: see declaration of 'ATemplate'
x.cpp(11): error C2079: 'y' uses undefined class 'ATemplate'

One of the answers below mention that override is meaningless in the context of free functions (valid point) - does this mean GCC is wrong here. The const specifier is also meaningless in that case (for free functions), but nevertheless permitted (by VC++)??? Also, it mentions that virtual specifiers should only exists in the declaration - this makes no difference to this case (as no definition exists). For the virtual keyword, it is OK to ommit in the derived as it makes no difference to whether code compiles, but for the override case it is not OK as it makes a big difference.

When using ReturnType (ArgType arg) ...possible const or override specifier as a macro parameter (like GMock does), the restriction imposed by VCC causes this code not to compile (apparently the case for Clang too). Which is right?

The standard does not state that the override specifier shall not be used in this context (the context of a template parameter?), does it?


It's a g++ bug.

The standard permits virt-specifier-sec in two productions: in a function-definition (only for virtual member-function definitions) and in a member-declarator. Your context is neither.

A shorter demo of GCC's buggy behaviour:

void foo(void) override;          // g++ rejects with message: 
                                  //  virt-specifiers in 'foo' 
                                  //  not allowed outside a class definition
void (*bar)(void) override;       // g++ erroneously accepts
typedef void baz(void) override;  // g++ erroneously accepts