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>;。)

詳細については、次を参照してください。 「template」および「typename」キーワードをどこに、なぜ配置する必要があるのですか?

于 2013-02-13T14:07:35.330 に答える
2

templateメソッド名の前に置く必要があります:

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

これは、テンプレート クラスBが解析されているとき、コンパイラはそれT::aがテンプレート化されたメソッドであることを認識していないためです (それTまで指定されT::aておらず、完全に不明であるため)。<double>.

それはまた意味することができ、実際には次のように解析されT::aます。もちろん、は式ではないので、これは失敗します。したがって、エラーメッセージ。そのため、コンパイラは、テンプレート化された関数呼び出しが必要であると想定することができます。ただし、型以外のテンプレート パラメーターを使用することもできます。たとえば、int などです。そのため、テンプレートではない未満よりも大きいとして解析できます。しかし、それをパラメータ付きのテンプレート パラメータ リストとして、次に引数付きの call-operatorとして解析する必要がありました。double(0)doubleT::a<42>(5)T::a42(5)T::a425

テンプレート化された関数呼び出しであることをコンパイラに伝えるにはtemplate、関数名の前に置く必要があります。

于 2013-02-13T14:08:04.337 に答える
0

コンパイラは T について何も知りません。そのため、記述するたびに、それが T のメンバー変数またはメソッドであるT::{something}と想定します。そうでない場合は、それが何であるかを伝える必要があります。参照しているのが変数ではなく型である場合に使用する必要が{something}あるキーワードについては、おそらく知っているでしょう。typenameテンプレートメンバーにも同様のトリックがあります:

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

これで、コンパイラaはテンプレートであり、その後に続くのはテンプレート パラメーター リストであることを認識します。

于 2013-02-13T14:10:21.260 に答える