3

为什么这段代码不能编译?

struct A {
    template <class T>
    static T a(int i) { return 2*i; }
};

template <class T>
struct B {
    double b;
    B(): b(T::a<double>(5)) {}
};

template class B<A>;

编译器甚至没有达到模板实例化。我正在使用 gcc 4.7.0。

test.cc: In constructor »B<T>::B()«:
test.cc:9:25: Error: expected »(« before »<« token
test.cc:9:26: Error: expected primary-expression before »double«
4

3 回答 3

6

您缺少template关键字,因为a它是从属名称(或类似名称)。

B(): b(T::template a<double>(5)) {}

(你的最后一行应该是template struct B<A>;。)

有关血腥的详细信息,请参阅: 我必须在哪里以及为什么要放置“模板”和“类型名称”关键字?

于 2013-02-13T14:07:35.330 回答
2

您必须template在方法名称之前放置:

B(): b(T::template a<double>(5)) {}

这是因为在B解析模板类时,编译器并不知道这T::a是一个模板化的方法(因为T到那时才指定,T::a完全未知),所以它不知道<double>应该被解析为模板参数列表.

它也可能意味着并且确实会被解析为:T::a小于double大于(0)。当然,doubleis 不是一个表达式,所以这失败了;因此错误消息。所以编译器可以假设你希望它是一个模板化的函数调用。但是你也可以有一个非类型的模板参数,比如一个 int,所以T::a<42>(5)可以被解析为T::a小于,42大于(5),这不是一个模板。但是您希望它被解析为T::a带有参数的模板参数列表,42然后是带有参数的调用运算符5

要告诉编译器这是一个模板化的函数调用,您必须template在函数名之前加上。

于 2013-02-13T14:08:04.337 回答
0

编译器对 T 一无所知。因此,每次编写T::{something}它时,它都假定它{something}是 T 的成员变量或方法。如果不是,则必须告诉它它是什么。typename如果您指的是类型而不是变量,您可能知道必须使用的关键字。模板成员也有类似的技巧:

template <class T>
struct B {
    double b;
    B(): b(T::template a<double>(5)) {}
};

现在编译器知道a是一个模板,然后是模板参数列表。

于 2013-02-13T14:10:21.260 回答