3

重複の可能性:
クラスが静的アサートと型特性を使用して 2 回派生するのを防ぐ方法はありますか?

私が防ぎたいのは、複数の C ベースのテンプレートが D で派生することです (つまり、派生する C のインスタンスは 1 つだけであるべきです)。これを解決する可能性のあるCまたはBの静的アサートを期待していました。

// My Classes
template <class T>
class A {};

class B {};

template <class T, class S>
class C : public B, public virtual A<T> {};

// Someone elses code using my classes
class D : public C<Type1, Type2>, public C<Type3, Type4>
{
};
4

1 に答える 1

5

現状では、より派生したクラスが他に何を継承しているBかを検出することは不可能であるため、そこにアサーションを追加することはできません。Cただし、「妙に再帰的な」テンプレート パラメータを追加することでC、派生クラスが何であるかを知ることができます。残念ながら、これには派生クラスが正しいテンプレート引数を与える必要があり、それを強制する方法はありません。

その後、派生クラスBが複数の方法で継承するかどうかを判断できます。これ基底クラスですが、派生クラス ポインターを変換することはできませんB*(その変換があいまいであるため)。これは必ずしも多重継承を示しているわけではないことに注意してください。非パブリック継承がある場合もテストは失敗します。

したがって、私が考えることができる最善の解決策は次のとおりです。

#include <type_traits>

template <class T> class A {};
class B {};

template <class T, class S, class D>
class C : public B, public virtual A<T> {
public:
    C() {
        static_assert(
            std::is_base_of<C,D>::value && std::is_convertible<D*,B*>::value, 
            "Multiple inheritance of C");
    }
};

struct Type1 {};
struct Type2 {};
struct Type3 {};
struct Type4 {};

class Good : public C<Type1, Type2, Good> {};
class Evil : public C<Type1, Type2, Evil>, public C<Type3, Type4, Evil> {};

int main()
{
    Good good;
    Evil evil; // Causes assertion failure
}

クラス テンプレートがインスタンス化されるときに一部の型が不完全であるため、クラス定義ではなくコンストラクターにアサーションを配置する必要がありました。残念ながら、これは実際にインスタンス化されたクラスに対してのみエラーが報告されることを意味します。

于 2012-01-13T15:08:50.613 に答える