首页 > 解决方案 > c++ constexpr指针和constexpr比较

问题描述

在以下代码中:

struct test{
    struct Data{};

    static constexpr const Data data1{};
    static constexpr const Data data2{};

    static constexpr const Data* pdata1 = &data1;
    static constexpr const Data* pdata2 = &data2;

    static constexpr const bool b1 = pdata1 == pdata2; // OK
    static constexpr const bool b2 = pdata1 != pdata2; // OK
    static constexpr const bool b3 = pdata1 <  pdata2; // ERROR: is not a constant expression
};

编译器允许我将指针与==和进行比较!=。但是<>导致编译器错误。为什么这样?

标签: c++constexpr

解决方案


比较两个不相关对象的地址有未指定的结果

[expr.rel]

3比较不相等的指向对象的指针定义如下:

  • 如果两个指针指向同一数组的不同元素或其子对象,则指向具有较高下标的元素的指针比较大。

  • 如果两个指针指向同一个对象的不同非静态数据成员,或者这些成员的子对象,递归地,如果两个成员具有相同的访问控制并且它们的类不是联盟。

  • 否则,没有一个指针比较大于另一个。

4如果两个操作数 p 和 q 比较相等,p<=q并且p>=q都产生 true,p<q并且p>q都产生 false。否则,如果指针 p 比较大于指针 q,则p>=q, p>q, q<=p, 和q<p都产生 true 并且p<=q, p<q, q>=p, 和q>p都产生 false。否则,每个运算符的结果都是未指定的。

并且明确禁止具有未指定结果的关系表达式出现在常量表达式中

[expr.const]

2表达式 e 是核心常量表达式,除非根据抽象机的规则对 e 的求值将求值以下表达式之一:

  • ...
  • 结果未指定的关系或等式运算符;或者
  • ...

当编译器在常量表达式的求值中遇到禁止的情况时,它需要发出诊断。因此你得到一个错误。

始终牢记 C++ 标准是根据抽象机器定义事物的。常量表达式是那些在该抽象机器中具有明确定义的语义的表达式,因此可以在所有参数都已知的情况下“在编译时”进行评估。如果抽象机中未指定某些内容,则无法生成定义良好的常量表达式,因此被禁止。


推荐阅读