2016-03-18 85 views
1

以下代码在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; 
} 

Demo

GCC - 误差:无模板参数使用的 '模板结构B'
铛 - 错误: 'B' 不是类,命名空间,或枚举

哪个编译器是符合标准规格?规格中的任何含糊之处?

编辑
我已在Cf()有一个更贴切的例证。

回答

3

通常调用在这种情况下,基类的功能,你可以这样写:

this->f(); 

如果fg都是静态的,你当然会无法做到这一点,因此,你可以写

B<T>::f(); 

这工作,因为B已经在为C申报范围,所以编译器已经知道它是一个模板。如果单独执行B::f(),编译器会给你一个错误,因为它知道B是一个模板,所以它应该有模板参数。

您可能想知道为什么允许您在B<T>的定义内省略模板参数,但不在C的定义范围内。为了理解这一点,你需要知道每个类都有一个注入类名,它的行为类似于类定义最开始处声明的typedef。因此,它是仿佛的B定义开始

typedef B<T> B; 

使用BB<T>定义里面会发现注入的类名,没有模板。但是当你在C之内时,这个B是不可见的,因为它是在B<T>内部声明的,这是一个依赖基类,并且在非限定名称查找期间不搜索依赖基类作用域(并且B位于::的左侧,所以查找B是不合格的)。这也适用于:

C::B::f(); 

在这种情况下,注入的类名C被找到,并且它是指依赖型C<T>,所以B查找将依赖基类中搜索B<T>和找到想要的注入类名称

1

问题出在struct C上,函数f from B被调用时没有模板参数。

0

编译器不知道您在B::f();中提到,请尝试将其更改为B<T>::f();

+0

对,我知道B :: f()的作品。开发跨平台代码,很烦人的是一些代码是用一个编译器而不是其他编译器编译的。我想知道它的标准是什么,如果三个编译器可以对齐以提供相同的编译结果(成功与否)... –