如何检查 C++ class 是否不完整(仅声明)?

How to check that a C++ class is incomplete (only declared)?

我想编写一个 C++ 函数来检查其模板参数 class 是否不完整,因此只有 class 声明可用但没有所有 class 成员的完整定义.

我的函数 incomplete() 与一些演示程序一起看起来如下:

#include <type_traits>
#include <iostream>

template <typename T, typename V = void> constexpr bool is_incomplete = true;
template <typename T> constexpr bool is_incomplete<T, std::enable_if_t<sizeof(T)>> = false;
template <typename T> constexpr bool incomplete() { return is_incomplete<T>; }

struct A;
void print() { std::cout << incomplete<A>(); }
struct A {}; //this line affects GCC

int main()
{
    print();
}

它在 Clang 打印中运行良好 1,但在 GCC 中程序打印 0 尽管 A class 在函数 [=16= 中不完整]. https://gcc.godbolt.org/z/qWW3hqbEv

这里是GCC错了还是我的程序有问题?

目前尚未确定哪个编译器是正确的。这是 CWG Issue 1845.

The current wording of 13.8.4.1 [temp.point] does not define the point of instantiation of a variable template specialization. Presumably replacing the references to “static data member of a class template” with “variable template” in paragraphs 1 and 8 would be sufficient.

鉴于该问题仍处于起草阶段(并且没有规范性措辞,但它是最新的可用草案),因此仍未解决。尚不清楚变量模板是否可以具有多个实例化点(尽管问题报告者建议的方向很明确)。

对于具有多个实例化点的实体,翻译单元的结尾也是一个。此外,如果有两点不同意模板的定义,那就是 ODR 违规,简单明了。 GCC 似乎提供了两点,因此您可以看到结果。我在这里倾向于同意 GCC。变量模板在许多方面是 shorthand 用于 class 模板的静态数据成员,而静态数据成员 确实有 多个实例化点。

不管怎么说,这都是在玩鼻魔的风险。如果一个 TU 中的状态可以改变(甚至可能在整个程序中改变),那么检查一个类型的完整性实际上是不可能的。

看起来 class 是否不完整将违反一个定义规则 (ODR),如果它在某个时候变得完整,所以应该没有有效的解决方案。

有人建议我引用 https://eel.is/c++draft/temp.point 中的更多内容:

1 For a function template specialization ... the point of instantiation ... immediately follows the namespace scope declaration or definition that refers to the specialization.

7 A specialization for a function template ... may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above,

for any such specialization that has a point of instantiation within the ... the translation-unit ..., the point after the ... [end of] the translation-unit is also considered a point of instantiation,

If two different points of instantiation give a template specialization different meanings according to the one-definition rule, the program is ill-formed, no diagnostic required.