C++ constexpr 指针和 constexpr 比较

c++ constexpr pointer and constexpr comparison

在下面的代码中:

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
};

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

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

[expr.rel]

3 Comparing unequal pointers to objects is defined as follows:

  • If two pointers point to different elements of the same array, or to subobjects thereof, the pointer to the element with the higher subscript compares greater.

  • If two pointers point to different non-static data members of the same object, or to subobjects of such members, recursively, the pointer to the later declared member compares greater provided the two members have the same access control and provided their class is not a union.

  • Otherwise, neither pointer compares greater than the other.

4 If two operands p and q compare equal, p<=q and p>=q both yield true and p<q and p>q both yield false. Otherwise, if a pointer p compares greater than a pointer q, p>=q, p>q, q<=p, and q<p all yield true and p<=q, p<q, q>=p, and q>p all yield false. Otherwise, the result of each of the operators is unspecified.

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

[expr.const]

2 An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions:

  • ...
  • a relational or equality operator where the result is unspecified; or
  • ...

当编译器在计算常量表达式时遇到禁止的内容时,它需要发出诊断。因此你得到一个错误。

永远记住,C++ 标准是根据抽象机来定义事物的。常量表达式是那些在该抽象机器中具有明确定义的语义的表达式,因此可以在所有参数已知时计算 "at compile time"。如果在抽象机中没有指定某些东西,它不能产生一个定义良好的常量表达式,所以它是被禁止的。