我试图在 static_assert
中验证通过比较静态字段上的指针,程序实际上具有从模板生成的两个不同的类。经过一些简化后,程序如下所示:
template<int N> struct C {
static int x;
};
template<int N> int C<N>::x = 0;
int main() {
static_assert(&C<0>::x != &C<1>::x);
}
Clang 没问题,但 GCC 打印错误:error: non-constant condition for static assertion
演示:https://gcc.godbolt.org/z/o6dE3GaMK我想知道这种类型的检查是否真的允许在编译时进行?
最佳答案
这应该是比答案更多的评论,但它不适合评论部分的可读方式。
所以关于这个问题的意图:
I was trying to verify in a
static_assert
that a program had really two distinct classes produced from a template by comparing the pointers on their static fields
您的代码片段是一个类的模板:
template<int N> struct C {
static int x;
};
这意味着它本身不是一个类,而是一个蓝图。实际类(class)是 C<0>
和 C<1>
.如果为 N
选择的值是不同的,那么结果类是不同的。要确定两种类型是否不同,您将使用(正如您在评论中正确提到的那样)
std::is_same_v
:static_assert( !std::is_same_v<C<0>,C<1>>);
不管static_assert(&C<0>::x != &C<1>::x);
是否有效,您不应该使用它来确定这些类型是否与语言的角度不同。在最坏的情况下,您会 - 由于请求成员的内存地址 - 阻止编译器进行一些以前可以进行的优化。现在你可以说编译器可以基于 as-if 做优化。并在这些类型之间共享部分,因此它们在二进制级别上没有区别(语言上的不同和二进制中的不同是两个不同的东西)。
但是由于相同的 as-if,无法在代码中真正测试这些在二进制级别上的不同程度。规则。
让我们暂时假设
static_assert(&C<0>::x != &C<1>::x);
会工作,然后 &C<0>::x != &C<1>::x
必须评估为 true
,因为 C<0>
和 C<1>
是不同的类型。这可能是由于两件事而发生的:x
的内存地址为 C<0>
和 C<1>
您实际上阻止编译器进行优化,然后他们将共享 x
在二进制级别上,所以二进制级别上的内存地址实际上是不同的。x
在 C<0>
之间共享和 C<1>
.但是&C<0>::x != &C<1>::x
的结果仍然是 true
因为它必须是 true
根据 as-if规则。所以即使地址是x
对于两种不同的类型 C<0>
和 C<1>
在二进制级别上相同 static_assert
测试将是 true
.关于c++ - 是否允许比较 static_assert 中静态类字段上的指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68987349/