由于类型不完整,在 static_assert 中使用 std::is_base_of 失败

using std::is_base_of in static_assert fails due to incomplete type

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

这可以像这样简单地实现:

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 class 显示扩展的好坏用法。

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

中缺少错误消息

What am I doing wrong ?

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

If Base and Derived are non-union class types and are not possibly cv-qualified versions of the same type, Derived shall be a complete type.

另一方面,[class.mem/6] 指出:

A class is considered a completely-defined object type (or complete type) at the closing } of the class-specifier. [...]

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

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