由于类型不完整

时间:2017-08-12 18:03:01

标签: c++ templates inheritance static-assert

我要做的是让一些类继承自extention类。问题是extention类必须知道它正在扩展哪个类。

这可以简单地实现:

template<typename Self>
class Extention
{
    public:
        void check() const
        {
            std::cout << "Extention is valid: "
                      << std::boolalpha
                      << std::is_base_of<Extention, Self>::value
                    << std::endl;
        }
};
class Foo : public Extention<Foo> {};
class Bar : public Extention<void> {};

FooBar类显示了扩展的良好和不良用法。

Foo().check(); → Extention is valid: true
Bar().check(); → Extention is valid: false

我想在编译期间检查模板的有效性,这让我写了

template<typename Self>
class Extention
{
    static_assert(std::is_base_of<Extention, Self>::value);
};

但是,gcc告诉我这个static_assert错误,因为class Foo的类型不完整。

我做错了什么?

修改:我使用-std=c++17,错误不是static_assert

中缺少错误消息

1 个答案:

答案 0 :(得分:2)

  

我做错了什么?

由于[meta.rel]std::is_base_of要求派生类型是完整类型:

  

如果BaseDerived是非联合类类型且不可能是相同类型的cv限定版本,则Derived应为完整类型。

另一方面,[class.mem/6]表示:

  

在类说明符的结束},类被视为完全定义的对象类型(或完整类型)。 [...]

那不是你的情况。当您实例化Extension<Foo>时,Foo本身远未完全定义。

换句话说,您不能在班级范围内使用static_assert。将它放在析构函数的主体中(实际上我的首选解决方案,即使它有一些缺点)或任何其他(特殊)成员方法的主体(如果您愿意)。