2011-08-15 11 views
31

私はテンプレート化されたclass(それにはFooと呼んでいます)にはいくつかの特殊化があります。誰かが未特定のバージョンのFooを使用しようとすると、コンパイルが失敗するようにしたいと思います。ここで特殊なテンプレートのインスタンス化を防ぐにはどうすればいいですか?

は、私が実際に持っているものです。

template <typename Type> 
class Foo 
{ 
    Foo() { cannot_instantiate_an_unspecialized_Foo(); } 

    // This method is NEVER defined to prevent linking. 
    // Its name was chosen to provide a clear explanation why the compilation failed. 
    void cannot_instantiate_an_unspecialized_Foo(); 
}; 

template <> 
class Foo<int> 
{ }; 

template <> 
class Foo<double> 
{ }; 

だから:

int main() 
{ 
    Foo<int> foo; 
} 

動作しますが:

int main() 
{ 
    Foo<char> foo; 
} 

はありません。

明らかに、コンパイラーチェーンは、リンク処理が行われるときにのみ不平を言います。しかし、以前にそれを不平にする方法はありますか?

boostを使用できます。

template <typename Type> 
class Foo; 

template <> 
class Foo<int> { }; 

int main(int argc, char *argv[]) 
{ 
    Foo<int> f; // Fine, Foo<int> exists 
    Foo<char> fc; // Error, incomplete type 
    return 0; 
} 

なぜこの作業を行います。

答えて

35

ちょうどクラスを定義していませんか?単にが存在しないため、の汎用テンプレートではありません。宣言されていますが、定義されていません。

+1

ありがとうございました。私はあまりにも複雑なものを探していたと思う。 – ereOn

+0

@Schnommusしかし、あなたがクラスを定義し、それがstatic_assertを持っているなら、特殊化がよりよく一致するので、インスタンス化されるべきではありませんか? –

+0

コンパイル時ではなく、リンクステージでエラーが発行されるため、間違った判断です。そして、あなたは、非専門クラスを正確に使った場所を決して知らないでしょう。 – vladon

17

あなたは単にベースケース定義することはできません:C++ 0X(C++ 03 static_assertエミュレーションとも使用できますが、エラーメッセージのトリックは必ずしも良好ではない

template <typename> class Foo;    // no definition! 

template <> class Foo<int> { /* ... */ }; // Foo<int> is OK 
+6

私はそれを逃したとは思わない...ありがとう。彼は評判が低いのでSchnommus答えを受け入れた。公正さのためにこれをアップしました。 – ereOn

13

を)未定義のプライマリテンプレートを残すより:

template<typename T> 
struct dependent_false: std::false_type {}; 

template<typename Type> 
struct Foo { 
    static_assert(dependent_false<Type>::value 
       , "Only specializations of Foo may be used"); 
}; 

Fooがプライマリテンプレートでインスタンス化されている場合、アサーションにのみトリガーされます。 static_assert(false, ...)を使用すると、アサーションが常にトリガされます。

+0

+1。トリックをありがとう。 – ereOn

+2

同様に、タイプする必要がないトリックは、static_assert(sizeof(Type)== 0、 "...")を使用することです。代わりに、BOOST_STATIC_ASSERTを使用することもできます。上記の "基本テンプレートを定義しない"は、単に参照/ポインタで作業するときにリンカーエラーにつながる可能性があるため、私は個人的にそれらを好む。テンプレートは一般的なものであり、ここでは制限していますので、実際にこれが必要な場合は、しばらくお待ちください。 – PlasmaHH

+0

これはどのように機能しますか? 'Specialization'ごとに' dependent_false :std :: true_type {} 'を定義する必要はないでしょうか?それとも' dependent_false :: value'は常にfalseでしょうか? – mako

関連する問題