我完全明白为什么无法工作:
class Base {};
class A;
static_assert(std::is_base_of<Base, A>::value, "");
因为没有关于“类层次结构”的信息,但...... 为什么以下不能工作?
class Base {};
class A : public Base {
static_assert(std::is_base_of<Base, A>::value, "");
};
(produce: an undefined class is not allowed as an argument to compiler intrinsic type trait)
类型'A'仍然不符合static_assert(根据此概念的定义)。但是 - 编译器已经知道'类层次结构'并且可以为此提供答案。
当然 - 这个static_assert可以移动到析构函数或其他什么来解决这个问题,但有些情况下无法完成,例如:
class Base {};
template<typename T>
struct type_of {
static_assert(std::is_base_of<Base, T>::value, "T is not derived from Base");
using type = int; //* Some normal type in real use
};
class A : public Base {
public:
type_of<A>::type foo(); // Will not compile
};
不应该被允许吗?
答案 0 :(得分:15)
在结束括号}
之后,类定义已完成(即,类被视为已定义)。
在您的情况下,当您尝试将A
与std::is_base_of
一起使用时,A
尚未完全定义:
class A : public Base {
// no closing brace for A yet, thus A isn't fully defined here
static_assert(std::is_base_of<Base, A>::value, "");
};
另一方面,std::is_base_of
要求完全定义的类型起作用
因此错误。
作为一种解决方法,您可以将断言放在A
的析构函数中:
class A : public Base {
~A() {
static_assert(std::is_base_of<Base, A>::value, "");
}
};
实际上,类类型在其成员函数体中被认为是完全定义的。
有关详细信息,请参阅soap-server
(强调我的):
在类说明符的结束时,类被视为完全定义的对象类型([basic.types])(或完整类型)。 在类成员规范中,该类在函数体,默认参数,noexcept-specifiers和默认成员初始值设定项(包括嵌套类中的此类事物)中被视为完整。否则,它在其自己的类成员规范中被视为不完整。
答案 1 :(得分:7)
The doc page std::is_base_of
收益:
如果Base和Derived都是非联合类类型,而它们不是 相同的类型(忽略cv资格),派生应该是完整的 输入强>;否则行为未定义。
使用}
关闭其范围后,类的定义已完成。因此,在您的情况下,会生成错误。
注意,static assertion可以出现在块或命名空间/文件范围中。所以你可以将它移到类的主体之外,或者,如果你不想在标题中有它,那么移动到实现文件。