3

可能重复:
有没有办法防止一个类使用静态断言和类型特征从两次派生?

我要防止的是不止一个基于 C 的模板在 D 中派生(即,应该只有一个 C 派生实例)。希望在 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

就目前而言,不可能BC检测到更多派生类继承自什么,因此您不能在那里添加断言。但是,通过添加“奇怪地递归”模板参数,您可以知道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 回答