Reputation: 4076
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
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
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
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