c++ - 是否允许比较 static_assert 中静态类字段上的指针?

标签 c++ language-lawyer static-assert

我试图在 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在二进制级别上,所以二进制级别上的内存地址实际上是不同的。
  • 编译器仍然进行优化,以便 xC<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/

    相关文章:

    c++ - P1359R0 [basic.lval]文字更改和别名规则

    c++ - 确保模板类不是多态的?

    c++ - Clang 和 GCC vs MSVC 和 ICC : Is a static_assert in the copy/move constructor required to work, 如果复制/移动省略也可以应用?

    c++ - 将指向数据成员的指针转换为 void *

    c++ - 我错过了使用数组的意义吗?

    c++ - 安装 Visual Studio 需要 40 多个小时

    c++ - 伪析构函数名称对非类和非枚举类型有意义吗?

    c - C 中 i++ 和 (i)++ 的区别

    c++ - 二进制 '=' : no operator found which takes a right-hand operand of type 'std::unique_ptr<char [],std::default_delete<_Ty>>'

    C++11 static assert for equality comparable type?