模板基类的调用方法

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;
}
Run Code Online (Sandbox Code Playgroud)

演示

gcc - 错误:“模板结构 B”在没有模板参数的情况下使用
clang - 错误:“B”不是类、命名空间或枚举

哪种编译器符合标准规范?规格中有任何含糊之处吗?

编辑
我添加了f()一个C更相关的示例。

Bri*_*ian 7

通常在这种情况下要调用基类函数,您可以编写:

this->f();
Run Code Online (Sandbox Code Playgroud)

如果fg都是静态的,你当然不能这样做,所以你可以写

B<T>::f();
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为B已经在 声明的范围内C,所以编译器已经知道它是一个模板。如果你B::f()单独这样做,编译器会给你一个错误,因为它知道它B是一个模板,所以它应该有模板参数。

您可能想知道为什么允许您在 的定义内省略模板参数,B<T>但在 的定义内却不能省略C。要理解这一点,您需要知道每个类都有一个注入类名,其行为类似于在类定义的最开头声明的 typedef。所以就好像 的定义B开始于

typedef B<T> B;
Run Code Online (Sandbox Code Playgroud)

B在 的定义中使用B<T>将找到注入的类名,而不是模板。但是当你在 inside 时C,这B是不可见的,因为它是在 inside 声明的B<T>,这是一个依赖基类,并且在非限定名称查找期间不会搜索依赖基类范围(并且B位于 的左侧::,因此 的查找B是非限定的) 。这也有效:

C::B::f();
Run Code Online (Sandbox Code Playgroud)

在这种情况下,找到了注入类名称 C,并且它引用了依赖类型C<T>,因此查找B将在依赖基类内部进行搜索B<T>并找到所需的注入类名称