現状では、より派生したクラスが他に何を継承している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
}
クラス テンプレートがインスタンス化されるときに一部の型が不完全であるため、クラス定義ではなくコンストラクターにアサーションを配置する必要がありました。残念ながら、これは実際にインスタンス化されたクラスに対してのみエラーが報告されることを意味します。