Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如果基类是成员函数的参数类型,是否需要指定基类的模板参数?_C++_Templates_Visual C++_Clang_Standards - Fatal编程技术网

C++ 如果基类是成员函数的参数类型,是否需要指定基类的模板参数?

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&

以下代码被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& 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

总的来说,我会这么说

  • 这是一个很好的角落箱子,而且

  • clang不检查
    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>
    };