2013-07-05 9 views
6

次のコードは、正当に見えるがあり、エラーであり、それが何を意味するのはなぜはテンプレートクラス

void f() {} 

template<bool> 
struct call_any 
{ 
    template<typename F> 
    static void call(F f) {} 
}; 

template<bool B> 
void call_f() 
{ 
    call_any<true>::call<void (&)()>(f); // OK 
    call_any<false>::call<void (&)()>(f); // OK 
    call_any<B>::call<void()>(f);   // OK 
    call_any<B>::call<void (&)()>(f); // expected primary-expression before '>' 
} 

をコンパイルしていないのテンプレートメソッドにパラメータとしての機能を渡しますか?

答えて

10

テンプレート内のテンプレートパラメータに依存する型を扱う場合、コンパイラは、その型のメンバがどんな種類のものであるかを知らない。他に指定しない限り、メンバは型ではなくテンプレートではないとみなされます。このため、より小さい演算子として<を処理しようとしていますが、>に達するまでにそのように式を解析することは不可能になります。あなたの代わりにこれを使用する必要がありますエラーを取り除くために

call_any<B>::template call<void (&)()>(f); 

これはcallはテンプレートなので、それはテンプレートパラメータとないの始まりとして<を扱う必要があることを明示的にコンパイラに指示します規則的でより小さい演算子。

これは、同様にtemplateを使用する必要があります:あなたは、この行にエラーが表示されていない

call_any<B>::call<void()>(f); 

唯一の理由は、非テンプレートとしてそれを解析する方法があるということです。

(call_any<B>::call < void()) > (f); 

奇数ではありますが、構文的には有効です。そのため、コンパイラはその行を超え、最初に表示されるエラーが表示されます。しかし、templateキーワードがなければ、call_fが実際にインスタンス化されると、最終的にはエラーが発生します(おそらく、うまくいく可能性があります)。

最初の2つの例は、templateキーワードを使用しないで問題ありません。型はテンプレートパラメータに依存しないため、call_fが解析されている間にcallがテンプレートであると判断できます。

質問:「なぜコンパイラはそれがテンプレートであるとわからないのですか?私はこれを上のコードのテンプレートとして定義しました!問題は特殊化です。あなたは、テンプレートを専門とし、主なテンプレートが指定するものとは完全に異なる何かをすることができます:

template<> 
struct call_any<false> 
{ 
    static const int call = 5; 
}; 

この専門call_fが定義された後も発生する可能性があるので、コンパイラはcall_anyの主なテンプレートが時に言うことに頼ることはできませんそれは構文解析していますcall_f

関連する問題