我有一段代码不能在Visual C ++ 2015下编译,但在GCC 4.8.4下编译。我想知道哪个是对的?有问题的代码如下:
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;
}
在下面(或const)使用覆盖作为说明符是不对的。 GMock库中存在类似的代码,其中宏扩展用于生成模板参数(包括覆盖)以及实际的函数签名。
删除注释掉的行时,Visual C ++ 2015会产生以下错误:
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'
下面提到的一个答案是覆盖在自由函数(有效点)的上下文中没有意义 - 这是否意味着GCC在这里是错误的。在这种情况下(对于自由函数), const说明符也没有意义,但仍允许(通过VC ++)???此外,它提到虚拟说明符应仅存在于声明中 - 这与此情况没有区别(因为不存在定义)。对于virtual关键字,可以在派生中省略,因为它对代码是否编译没有区别,但对于覆盖情况,它不是好的,因为它会产生很大的不同。
当使用 ReturnType(ArgType arg)...可能的const或覆盖说明符作为宏参数(如GMock那样)时,VCC强加的限制导致此代码无法编译(显然是这种情况)对于Clang来说)。哪个是对的?
标准没有说明在这种情况下(模板参数的上下文?)不应该使用覆盖说明符,是吗?
答案 0 :(得分:8)
这是一个g ++错误。
该标准在两个作品中允许 virt-specifier-sec :在函数定义中(仅适用于virtual
成员函数定义)和构件声明符。你的背景不是。
GCC错误行为的简短演示:
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
答案 1 :(得分:5)
根据标准,override
说明符是上下文相关的,并且在成员函数声明后使用时具有仅的特殊含义;否则,它不是保留的关键字。
所以我想说,你的第二个例子中的代码似乎毫无意义。
我尝试使用gcc-5.1.0
(带-S标志)编译这两个示例,它们会产生完全相同的程序集。
它不在clang-3.7.0
下编译,导致以下错误:
test.cpp:11:23: error: expected '(' for function-style cast or type construction
实际上,这意味着你不应该以这种方式使用覆盖。
答案 2 :(得分:2)
来自 9.2班级成员(草案N4140)
virt-specifier-seq:
virt-specifier
virt-specifier-seq virt-specifier
virt-specifier:
override
final
[9.2 / 8]
virt-specifier-seq 最多应包含每个 virt-specifier 中的一个。 virt-specifier-seq 只能出现在 宣布虚拟成员函数(10.3)。
据我所知,override
不能应用于自由函数,所以我不希望它被允许在自由函数的签名/类型中(即使它是部分类似const
)。