以下代码在visual studio 2015中编译(即使使用/ Za选项)。它不能在gcc和clang上编译。
struct A
{
};
template<typename T>
struct B
{
void f()
{
}
};
template<typename T>
struct C : B<T>
{
void f()
{
}
void g()
{
B::f();
}
};
int main()
{
C<A> c;
c.g();
return 0;
}
gcc - 错误:'模板结构B'没有模板参数使用
clang - 错误:'B'不是类,命名空间或枚举
哪种编译器符合标准规范?规格中有任何含糊之处吗?
修改
我在f()
中添加了C
以获得更相关的示例。
答案 0 :(得分:4)
通常在这种情况下调用基类函数,你会写:
this->f();
如果f
和g
都是静态的,那么你当然无法做到这一点,所以你可以写一下
B<T>::f();
这是有效的,因为B
已经在C
的声明范围内,因此编译器已经知道它是一个模板。如果你单独B::f()
,编译器会给你一个错误,因为它知道B
是一个模板,所以它应该有模板参数。
您可能想知道为什么允许您在B<T>
的定义中省略模板参数,但不在C
的定义中。要理解这一点,您需要知道每个类都有一个 inject-class-name ,其行为类似于在类定义的最开始声明的typedef。所以好像B
的定义以
typedef B<T> B;
在B
的定义中使用B<T>
会找到 inject-class-name ,而不是模板。但是当你在C
内时,这个B
是不可见的,因为它是在B<T>
内声明的,它是一个从属基类,并且在非限定名称查找期间不会搜索依赖的基类范围(B
位于::
的左侧,因此B
的查找不合格。这也有效:
C::B::f();
在这种情况下,找到了注入类名 C
,它引用了依赖类型C<T>
,因此B
的查找将在依赖基类B<T>
内搜索并找到所需的注入类名。
答案 1 :(得分:1)
问题出在struct C
,来自f
的函数B
在没有模板参数的情况下被调用。
答案 2 :(得分:0)
编译器不知道您在B
中引用的B::f();
,请尝试将其更改为B<T>::f();
。