使用模板参数的静态成员模板

时间:2013-02-13 14:01:51

标签: c++ templates

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

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«

3 个答案:

答案 0 :(得分:6)

您错过了template个关键字,因为a是一个从属名称(或类似名称)。

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

(您的最后一行也应为template struct B<A>;。)

有关血淋淋的细节,请参阅: Where and why do I have to put the "template" and "typename" keywords?

答案 1 :(得分:2)

您必须在方法名称前添加template

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

这是因为在解析模板类B时,编译器不知道T::a是模板化方法(因为在此之前未指定T,并且{{ 1}}完全未知),因此它不知道T::a应该被解析为模板参数列表。

它也可能意味着并且确实将被解析为:<double>小于T::a大于double。当然,(0)不是表达,所以这很脆弱;因此错误信息。所以编译器可能只是假设你希望它是一个模板化的函数调用。但是你也可以有一个非类型的模板参数,例如一个int,所以double可以解析为T::a<42>(5)小于T::a大于42,不是模板。但您希望将其解析为(5),然后将参数T::a解析为模板参数列表,然后使用参数42解析调用操作符。

要告诉编译器它是一个模板化的函数调用,你必须在函数名之前加上5

答案 2 :(得分:0)

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

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

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