C ++验证模板类型

时间:2018-09-09 18:41:10

标签: c++ templates template-meta-programming

对不起,我的英语不好,我会尽力而为。

我想设计一个应该像这样使用的接口:

class MyObject : public IMyInterface<MyObject>
{
    // ...
};

界面可能如下所示:

template <class _TMyObject>
class IMyInterface
{
    virtual _TMyObject* Get() = 0;
};

我要照顾的是一种在编译时验证接口是否按预期使用的方法。 如何测试_TMyObject是否为IMyInterface<_TMyObject>?在接口定义内部,例如带有static_assert的

感谢您的帮助:)。 祝你有美好的一天!

2 个答案:

答案 0 :(得分:6)

您不能将static_assert放在类本身内,因为D是不完整的类型,但是您可以将其放在析构函数(或构造函数,但可以有很多构造函数)中:< / p>

template<class D>
struct B
{
    ~B()
    {
        static_assert(std::is_base_of_v<B, D>);
    };
};

struct Not_E {};

struct D : B<D> { };         
struct E : B<Not_E> { };     

void foo()
{
     D d;     // OK
     E e;     // Fails
}

添加。。请注意,此解决方案并不是防止CRTP错误使用的完整保护措施。请参考 Some Programmer Dude 的答案,以获取无法捕获的错误示例。

答案 1 :(得分:2)

自C ++ 11起,many type property traits可用于在编译时进行检查。

例如std::is_base_of,在您的情况下,它可能会被使用

localhost/my_site_folder/public/images/example.png?d41d8cd98f00b204e9800998ecf8427e

注意:上面显示的确切代码不能直接使用,而是可以显示原理。

当然,确实允许类似

template<typename TChild>
struct IMyInterface
{
    static_assert(std::is_base_of<IMyInterface, TChild>::value, "Derived class not derived from IMyInterface");

    // ...
};

因此,如果可以进行此类检查,请回答您的问题:不是您想要的方式。即使使用其他特征和元编程,也不能保证在CRTP中使用时,接口类的模板参数是“正确的”。

我唯一能看到它工作的方法是在运行时使用class MyFirstClass : public IMyInterface<MyFirstClass> { // ... }; // Note wrong class in template // vvvvvvvvvvvv class MySecondClass : public IMyInterface<MyFirstClass> { // ... }; 进行向下广播,类似于接口类中的dynamic_cast