4

テンプレートが受け取ることができる引数の種類を正確に指定できますか? たとえば、 class または class を拡張するクラスでのみインスタンス化できるテンプレートを作成したいと思いますA。Java では、ジェネリックは次の方法でこれをサポートします。

class B<T extends A> { }

C++ のテンプレートで同様のことを実現できますか?

template <typename T (?)> class B { }
4

2 に答える 2

3

あなたはとでこれを行うことができstatic_assertますis_base_of

#include <type_traits>
template<typename T> class D {
    static_assert(std::is_base_of<A, T>::value, "must be derived from A");
};

または、次を使用できますenable_if

#include <type_traits>
template<typename T, typename = void> class D;
template<typename T> class D<T, typename std::enable_if<std::is_base_of<A, T>::value>::type> {
};

C ++ 03の場合、ブーストを使用できます。Boost.TypeTraitsis_base_ofから、Boost.StaticAssertから、Boost.EnableIfから。static_assertenable_if

于 2012-08-15T06:51:58.643 に答える
3

これには 2 つの方法があります。

まず、as 条件で使用する非表示のダミー テンプレート パラメーターを使用std::enable_ifstd::is_base_of<A, T>::valueます。後者の式が に評価される場合false、ネストされたtypeは に存在しませんstd::enable_if。オーバーロードされた関数でこれを使用していた場合、SFINAE は「置換の失敗はエラーではない」ことを意味し、問題のオーバーロードは実行可能な関数のセットから削除されます。ただし、この状況では、呼び出しに一致する他のクラス テンプレートがなく、コンパイル時エラーが発生します。

SFINAE は非常に微妙なメカニズムであり、間違えやすいです。たとえば、異なる SFINAE 条件を持つ複数のクラス特殊化がある場合、それらがすべて重複していないことを確認する必要があります。そうしないと、あいまいさが生じます。

2 つ目は、クラスの本体内で簡単static_assertに実行できます。std::is_base_of<A,T>::valueこの方法の利点は、SFINAE 方法よりも読みやすいエラー メッセージを指定できることです。欠点は、常にエラーが発生し、この特定のテンプレートを黙って抑制して別のテンプレートを選択できないことです。しかし、全体として、この方法はあなたの場合に推奨されると思います。

#include<type_traits>

class A {};
class C: public A {};
class D {};

// first alternative: SFINAE on hidden template parameter
template
<
    typename T, 
    typename /* dummy */ = typename std::enable_if< 
        std::is_base_of<A, T>::value
    >::type
>
class B
{
};

// second alternative: static_assert inside class
template
<
    typename T
>
class E
{
    static_assert(std::is_base_of<A, T>::value, "A should be a base of T");
};

int main()
{
    B<A> b1;
    B<C> c1;
    //B<D> d1; // uncomment this line to get a compile-time error

    E<A> b2;
    E<C> c2;
    //E<D> d2; // uncomment this line to get a compile-time error

    return 0;
}

コメントで指摘されているように、適切な C++11 コンパイラ (VC++ 2010 以降、gcc 4.5 以降) または Boost または TR1 ライブラリを使用して<type_traits>機能を取得できます。ただし、 は にstd::is_base_of<A, A>::value評価されtrueますが、古いものは に評価されることに注意boost::is_base_of<A, A>::valueしてくださいfalse

于 2012-08-15T06:50:39.453 に答える