C++ 由于类型不完整,在静态_断言中使用std::is_base_失败

C++ 由于类型不完整,在静态_断言中使用std::is_base_失败,c++,templates,inheritance,static-assert,C++,Templates,Inheritance,Static Assert,我想做的是让一些类从扩展类继承。问题是扩展类必须知道它正在扩展哪个类 这可以简单地通过以下方式实现: template<typename Self> class Extention { public: void check() const { std::cout << "Extention is valid: " << std::boolalpha

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

这可以简单地通过以下方式实现:

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> {};
我想在编译过程中检查模板的有效性,这让我开始编写

template<typename Self>
class Extention
{
    static_assert(std::is_base_of<Extention, Self>::value);
};
模板
类扩展
{
静态断言(std::是::值的基础);
};
但是,gcc告诉我这个
静态断言
是错误的,因为
类Foo
的类型不完整

我做错了什么

编辑:我使用的是
-std=c++17
,错误不是因为
静态断言中缺少错误消息

我做错了什么

因为,
std::is_base_of
要求派生类型是完整类型:

如果
Base
Derived
是非联合类类型,并且不可能是同一类型的cv合格版本,
Derived
应为完整类型

另一方面,缔约国表示:

类在类说明符的结尾处被视为完全定义的对象类型(或完全类型)。[……]

那不是你的情况。当您实例化扩展时,
Foo
本身还远远没有完全定义


换句话说,您不能在类范围中使用该
static\u assert
。将其放入析构函数体(实际上是我的首选解决方案,尽管它有一些缺点)或任何其他(特殊)成员方法体(如果您愿意)。

您可以将
static\u assert
放入成员函数中,但要使其工作,您必须实例化该函数(可能通过调用它)@HolyBlackCat将其放入构造函数将起作用。尽管如此,如果您有多个构造函数,这将是痛苦且容易出错的……与其用静态断言攻击所有构造函数,从受保护的
Requiredived
派生模板
extension
是一个选项吗?这将为您提供一个受根保护的默认构造函数,
RequiredBase()
,用于挂起静态断言。或者我误解了你的目标。那么把它放进析构函数怎么样?@WhozCraig:可以,但感觉设计过度了。HolyBlackCat:会更有效,感觉更优雅。不过,我们应该能够将断言直接放入类中。。。
template<typename Self>
class Extention
{
    static_assert(std::is_base_of<Extention, Self>::value);
};