2013-02-13 86 views
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« 
+1

也许你可以提供编译器的错误信息? – ronag 2013-02-13 14:03:29

+0

对不起,我忘了 – 2013-02-13 14:05:37

回答

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?

2

你有方法的名称前把template

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

这是因为当解析模板类B时,编译器不会知道T::a是一种模板化方法(因为T在此之前未指定,并且T::a完全未知),所以它不知道<double>应该被解析为模板参数列表。

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

要告诉编译器它是一个模板函数调用,必须在函数名称前加template

0

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

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

现在编译器知道a是一个模板和什么来之后是模板参数列表。

相关问题