C++ 如果基类是成员函数的参数类型,是否需要指定基类的模板参数?
以下代码被VC++2013接受,但被clang 3.4拒绝C++ 如果基类是成员函数的参数类型,是否需要指定基类的模板参数?,c++,templates,visual-c++,clang,standards,C++,Templates,Visual C++,Clang,Standards,以下代码被VC++2013接受,但被clang 3.4拒绝 哪个编译器是按照C++标准的? template<class T> struct A { T n; }; template<class T> struct B : A<T> { // VC++ 2013 : OK // clang : error : use of class template 'A' requires template arguments B&
哪个编译器是按照C++标准的?
template<class T>
struct A
{
T n;
};
template<class T>
struct B : A<T>
{
// VC++ 2013 : OK
// clang : error : use of class template 'A' requires template arguments
B& f1(const A& obj)
{
return *this;
}
// VC++ : OK
// clang : OK
B& f2(const A<T>& obj)
{
return *this;
}
};
int main()
{
B<int> b;
}
模板
结构A
{
T n;
};
模板
结构B:A
{
//VC++2013:好的
//叮当声:错误:使用类模板“A”需要模板参数
B&f1(建筑A&obj)
{
归还*这个;
}
//VC++:好的
//叮当声:好的
B&f2(常数A&obj)
{
归还*这个;
}
};
int main()
{
B B;
}
我的第一反应是说VC++在这方面是正确的。在B
中查找名称A
应在A
中找到注入的类名A
,该类名也可用作引用A
的类型名
C++11[临时本地]:
1与普通(非模板)类一样,类模板具有注入类名称(第9条)。注入的类名可以用作模板名或类型名。当它与模板参数列表一起使用时,作为模板参数的模板参数,或作为详细类型说明符中的最终标识符
对于friend类模板声明,它引用类模板本身。否则,它是等价的
添加到模板名称,后跟
中包含的类模板的模板参数
2
3类模板或类模板专门化的注入类名称可以用作模板名称
或类型名称,无论其位于范围中的任何位置。[示例:
模板结构库{
碱基*p;
};
派生的模板结构:公共基{
typename派生::Base*p;//表示派生::Base
};
然而,同时,[临时部门]第3条规定:
3在类或类模板的定义中,如果基类依赖于模板参数,则基类
在非限定名称查找期间,在类模板的定义点也不检查作用域
或成员,或在类模板或成员的实例化过程中
基于此,我更倾向于说clang实际上是正确的,因为注入的类名A
在A
的范围内,这取决于B
的模板参数T
,因此在非限定名称查找过程中不会被搜索。支持这一点的第二个证据是examp来自[temp.local]的le使用Derived::Base
而不是Base
总的来说,我会这么说
A
Clang是正确的;尽管类模板
A
的注入类名肯定在A
中可见,并且在派生类B
中可见,但它是一个从属名称,因此在B
中不检查基类范围
14.6.2p3中讨论了从属名称基类范围查找:
在类或类模板的定义中,如果基类依赖于模板参数,则在类模板或成员的定义点或类模板或成员的实例化过程中,在非限定名称查找期间不会检查基类范围
14.6.1/3(在n3337中,如果相关的话)@jrok谢谢,正在看它。但是,我最终不得不重新表述我的结论,基于14.6.2/3注意,g++也会发出一个错误()。看起来是标记的主要候选,但你已经5岁了。。。
template <class T> struct Base {
Base* p;
};
template <class T> struct Derived: public Base<T> {
typename Derived::Base* p; // meaning Derived::Base<T>
};