如何使用静态断言和类型特征阻止嵌套模板类型中的菱形图案?

Jai*_*ime 3 c++ templates static-assert type-traits

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

我想要防止的是不止一个基于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>
{
};
Run Code Online (Sandbox Code Playgroud)

Mik*_*our 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
}
Run Code Online (Sandbox Code Playgroud)

我必须将断言放在构造函数而不是类定义中,因为在实例化类模板时,某些类型是不完整的.不幸的是,这意味着只会报告实际实例化的类的错误.