【问题标题】:Using static member templates of a template parameter [duplicate]使用模板参数的静态成员模板[重复]
【发布时间】:2013-02-13 14:01:50
【问题描述】:

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

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«

【问题讨论】:

  • 也许你可以提供编译器错误信息?

标签: c++ templates


【解决方案1】:

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

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

(最后一行应该是template struct B&lt;A&gt;;。)

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

【讨论】:

  • 啊,谢谢,我总是忘记那个。
  • 关于template struct B&lt;A&gt;...根据标准的推荐,任何一个都是正确的。遗憾的是,一些编译器(即微软的)并不总是遵守标准。
【解决方案2】:

你必须在方法名前加上template

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

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

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

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

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多