C++ 为什么可以';";是“U基”还是“U基”;是否在类声明中使用(不完整类型)?

C++ 为什么可以';";是“U基”还是“U基”;是否在类声明中使用(不完整类型)?,c++,static-assert,incomplete-type,C++,Static Assert,Incomplete Type,我完全明白为什么这个不能工作: class Base {}; class A; static_assert(std::is_base_of<Base, A>::value, ""); 类基{}; 甲级; 静态断言(std::是::value“”的基础; 因为没有关于“类层次结构”的信息,但是。。。 为什么不能进行以下工作 class Base {}; class A : public Base { static_assert(std::is_base_of<Base

我完全明白为什么这个不能工作:

class Base {};
class A;
static_assert(std::is_base_of<Base, A>::value, "");
类基{};
甲级;
静态断言(std::是::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类:公共基地{
静态断言(std::是::value“”的基础;
};
(product:不允许未定义的类作为编译器内在类型trait的参数)
类型“A”与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
};
类基{};
模板
结构类型{
static_assert(std::is_base_of::value,“T不是从base派生的”);
使用type=int;//*一些实际使用的普通类型
};
A类:公共基地{
公众:
type of::type foo();//将不编译
};

不允许吗?

在右大括号
}

在您的情况下,当您尝试将
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, "");
};
事实上,类类型被认为是在其成员函数的主体中完全定义的


有关更多详细信息,请参见:

在类说明符的结尾}处,类被视为完全定义的对象类型([basic.types])(或完全类型)在类成员规范中,类在函数体、默认参数、noexcept说明符和默认成员初始值设定项(包括嵌套类中的此类内容)中被视为完整的。否则,在其自身的类成员规范中,它被视为不完整的

对于
std::is_base_of
产量:

如果基类和派生类都是非并集类类型,而它们不是 同一类型(忽略cv资格),衍生应为完整的 类型;否则,行为是未定义的

使用
}
关闭类的作用域后,类的定义就完成了。因此,在您的情况下,将生成一个错误



注意,它可以出现在block命名空间/文件范围中。因此,您可以将它移到类的主体之外,或者,如果您不想将它放在标题中,则移到实现文件。

编译器已经知道“类层次结构”
是的,但是
std::is_base of
不是一个核心功能,而是一个库功能,这使得事情变得更复杂。@DeiDei:换句话说,因为C++是一个又一个巨大的抽象漏洞"? ;)目前的is_base_是一个非常普通的类模板。为了实现您的想法,您需要is_base_of的特殊魔法实现以及执行此魔法的标准的特殊许可。标准已经太大了。为了边际效益,我们不想让它变得更大、更复杂。我们不想让它变得更大、更复杂@n.m。请你自己说:p没有什么大魔法-只是逻辑:)如果一个功能不需要了解关于类的所有信息,只需要了解它的“类层次结构”——为什么会这样。欢迎你写一个建议。“类类型被认为是在其成员函数的主体中完全定义的”…这是一个很好的观点!请参见-类被认为是完全定义的对象类型([basic.types])(或完全类型)在类说明符的}结尾处。在类成员规范中,类在函数体、默认参数、noexcept说明符和默认成员初始值设定项(包括嵌套类中的此类内容)中被视为完整的。否则,它在其自身的类成员规范中被视为不完整。问题是问为什么会出现这种情况,而不仅仅是为了肯定它是这样。
class A : public Base {
    ~A() {
        static_assert(std::is_base_of<Base, A>::value, "");
    }
};