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

Using static member templates of a template parameter

本文关键字:静态成员 参数      更新时间:2023-10-16

为什么不编译此代码?

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«

您缺少一个template关键字,因为a是一个依赖名称(或类似名称)。

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

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

有关血腥的详细信息,请参阅:我必须把";模板";以及";typename";关键词?

您必须将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放在函数名之前。

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

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

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