2014-01-14 11 views
11

次のコードビットは、エラーメッセージ4.5.3インスタンスエラー後のメンバ関数テンプレートの特殊化、およびメンバ関数の順序は

struct Frobnigator 
{ 
    template<typename T> 
    void foo(); 

    template<typename T> 
    void bar(); 
}; 

template<typename T> 
void Frobnigator::bar() 
{ 
} 

template<typename T> 
void Frobnigator::foo() 
{ 
    bar<T>(); 
} 

template<>  // error 
void Frobnigator::foo<bool>() 
{ 
    bar<bool>(); 
} 

template<> 
void Frobnigator::bar<bool>() 
{ 
} 

int main() 
{ 
} 

GCCでコンパイルすることができない:specialization of ‘void Frobnigator::bar() [with T = bool]’ after instantiation。最終的にFrobnigator::foo<bool>()の前にFrobnigator::bar<bool>()の特殊化を表示することでこの問題を解決しました。明らかに、メソッドが問題に見える順序。

上記のコードのうち、barの特殊化がジェネリックバージョンの後に表示されるのはなぜですか?

struct Frobnigator 
{ 
    template<typename T> 
    void foo(); 
}; 

template<typename T> 
void Frobnigator::bar() 
{ 
} 

template<> 
void Frobnigator::bar<bool>() 
{ 
} 

int main() 
{ 
} 

答えて

18

最初のコードは標準では正しくありません。/6

n3376 14.7.3は、テンプレート場合は、メンバーテンプレートまたはクラステンプレートのメンバーは、明示的に専門暗黙の原因となること専門の最初の使用前に宣言されなければならないことを、その後特化していますインスタンス化 は、このような使用が行われるすべての翻訳単位でとなります。診断は必要ありません。あなたのケースでは

- タイプboolbar関数の暗黙のインスタンス生成は、明示的な特殊宣言の前に、foo<bool>にその使用によって必要とされます。

2

明らかに、その方法が重要と思われる順序。

実際、通常はC++のように、宣言される前に何かを使うことはできません。これは明示的なテンプレートの特殊化や他のほとんどのものに適用されます。

bar<bool>(それをfoo<bool>から呼び出すことによって)明示的な特殊化の宣言がない場合、その特殊化は、未だ作成されていない場合は、汎用テンプレートからインスタンス化されます。それを防ぐには、明示的な専門化の宣言が少なくとも必要です。

なぜこれがバーの専門は、2番目の例では、全くfoo<bool>をインスタンス化しないことによって異なり、上記のコードの次liteのバージョン

におけるジェネリック版の後に表示されていることを考慮すると、ケースです。問題は、特殊化が汎用テンプレートの後に宣言されているわけではありませんが、その特殊化が既にインスタンス化された後に宣言されているということではありません。

関連する問題