在static_assert中使用std :: is_base_of由于不完整类型而失败
问题描述:
我想要做的是将一些类继承为extention
类。事情是extention
类必须知道它正在扩展的类。在static_assert中使用std :: is_base_of由于不完整类型而失败
这可以简单地实现这样的:
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> {};
的Foo
和Bar
类节目好,进一步扩展的不好的用法。
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
答
缺少错误消息的我在做什么错?
由于[meta.rel],std::is_base_of
要求派生类型是一个完整的类型:
如果
Base
和Derived
都是非工会类类型,不属于同一类型的可能CV-合格版本,Derived
应是完整的类型。
在另一侧,[class.mem/6]指出:
一类被认为是在类说明符的关闭
}
完全定义的对象类型(或完整的类型)。 [...]
这不是你的情况。当您实例化Extension<Foo>
时,Foo
本身远未完全定义。
换句话说,您不能在类作用域使用static_assert
。如果你愿意的话,把它放在析构函数体内(我的首选解决方案,即使它有一些缺点)或任何其他(特殊)成员方法的正文。
您可以将'static_assert'放入成员函数中,但要使其正常工作,必须通过调用它来实现该函数。 – HolyBlackCat
@HolyBlackCat把它放在构造函数中会起作用。不过,如果你有多个构造函数,它会是痛苦和容易出错的... – Amxx
而不是使用静态断言敲击所有构造函数,而是从受保护的'Requiredived'派生模板'Extention'是'Self'选项?这会给你一个根保护的默认构造函数'RequiredBase()',在其中挂起你的静态断言。或者,也许我误解了你的目标。 – WhozCraig