Werner Erasmus
Werner Erasmus

Reputation: 4076

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?

Upvotes: 12

Views: 962

Answers (3)

n. m. could be an AI
n. m. could be an AI

Reputation: 119877

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

Upvotes: 8

oo_miguel
oo_miguel

Reputation: 2379

According to the standard the override specifier is context-sensitive and has special meaning only when it's used after a member function declaration; otherwise, it's not a reserved keyword.

So i would say, the code in your second example seems meaningless.

I tried compiling your both examples with gcc-5.1.0 (with the -S flag) and they result in exactly the same assembly.

It does not compile under clang-3.7.0 resulting in the following error:

test.cpp:11:23: error: expected '(' for function-style cast or type construction

Pracitcally it means you should not use override in that way.

Upvotes: 5

melak47
melak47

Reputation: 4850

From 9.2 Class members (draft N4140)

virt-specifier-seq:
    virt-specifier
    virt-specifier-seq virt-specifier
virt-specifier:
    override
    final

[9.2/8]

A virt-specifier-seq shall contain at most one of each virt-specifier. A virt-specifier-seq shall appear only in the declaration of a virtual member function (10.3).

So as far as I can see, override can not be applied to free functions, so I wouldn't expect it to be allowed in the signature/type of a free function (even if it was part of the type like const).

Upvotes: 2

Related Questions