4
struct B
{
    int a;
    void foo() {a = 5;}
};

template <typename T>
struct A
{
    A(int i) { B::foo(); }
    A(double d) {}
};

int main()
{
    A<int> a(5.0);
}

gcc 4.7.2 编译它没有错误。clang 3.4svn 抱怨:

$ clang -Wall -Wextra test.cpp 
test.cpp:10:16: error: call to non-static member function without an object argument
        A(int i) { B::foo(); }
                   ~~~^~~

代码当然是错的,但是哪个编译器符合标准呢?

如果您使用 5 而不是 5.0,clang 不会像 gcc 那样打印任何“实例化”注释,这也很奇怪:

$ gcc test.cpp 
test.cpp: In instantiation of ‘A<T>::A(int) [with T = int]’:
test.cpp:15:12:   required from here
test.cpp:9:13: error: cannot call member function ‘void B::foo()’ without object
4

1 回答 1

5

您的程序不正确,并且两个编译器都是正确的,因为该标准不需要来自符合标准的编译器的诊断(让 gcc 忽略它)。没有有效实例化(标准术语中的专门化)的模板是不正确的,即使该模板从未被实例化。

在你的情况下,B::foo()里面的名字A<T>::A(int)是一个非依赖的名字,所以需要在第一阶段查找的时候进行解析,并且只能引用B上面定义的类。因为它不是一个static成员函数,而是一个非静态的,所以代码是不正确的,无论T用于实例化A<T>模板的类型是什么,程序都是不正确的。

相关报价来自 14.6 [temp.res]/8:

知道哪些名称是类型名称可以检查每个模板定义的语法。对于可以生成有效特化的模板定义,不应发出诊断。如果无法为模板定义生成有效的特化,并且该模板未实例化,则模板定义格式错误,无需诊断。

于 2013-07-11T16:44:26.427 回答