Dan*_*ügt 4 c++ gcc clang visual-c++ visual-studio-2015
以下代码在 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更相关的示例。
通常在这种情况下要调用基类函数,您可以编写:
this->f();
如果f和g都是静态的,你当然不能这样做,所以你可以写
B<T>::f();
这是有效的,因为B已经在 声明的范围内C,所以编译器已经知道它是一个模板。如果你B::f()单独这样做,编译器会给你一个错误,因为它知道它B是一个模板,所以它应该有模板参数。
您可能想知道为什么允许您在 的定义内省略模板参数,B<T>但在 的定义内却不能省略C。要理解这一点,您需要知道每个类都有一个注入类名,其行为类似于在类定义的最开头声明的 typedef。所以就好像 的定义B开始于
typedef B<T> B;
B在 的定义中使用B<T>将找到注入的类名,而不是模板。但是当你在 inside 时C,这B是不可见的,因为它是在 inside 声明的B<T>,这是一个依赖基类,并且在非限定名称查找期间不会搜索依赖基类范围(并且B位于 的左侧::,因此 的查找B是非限定的) 。这也有效:
C::B::f();
在这种情况下,找到了注入类名称 C,并且它引用了依赖类型C<T>,因此查找B将在依赖基类内部进行搜索B<T>并找到所需的注入类名称。