使用std :: less和nullptr

Ale*_*der 12 c++ c++11

以下代码段中的断言是否始终有效?

std::less<Object *> lessPtr;
Object * o = new Object();
assert(lessPtr (o, nullptr) == false);
Run Code Online (Sandbox Code Playgroud)

Fil*_*efp 18

介绍

这个问题实际上归结为在一个操作数为a的指针类型上使用小于关系运算符是否nullptr会产生"预期"结果; 遗憾的是并非如此.

结果未指定.

注:请记住,std::less保证了全序 ; 意味着即使结果在使用函数对象时未指定,它也必须在每次调用时产生相同的未指定值.


国际标准(N3337)说什么?

5.9p2 关系运算符 [expr.rel]

可以比较指向相同类型的对象或函数的指针(在指针转换之后),结果定义如下:

  • 如果两个指针pq相同类型的指向相同的对象或功能或两者点一个过去的同一阵列的端部,或均为空,则p<=qp>=q两个产量truep<qp>q二者产量false.

  • 如果两个指针pq相同类型的点不属于相同对象的成员或相同数组的元素不同的对象或不同的功能,或者如果只有它们中的一个为空,结果p<q,p>q,p<=q,和p>=q未指定.

  • 如果两个指针指向同一对象的非静态数据成员,或者指向这些成员的子对象或数组元素,则递归地指向稍后声明的成员的指针比较更大,前提是两个成员具有相同的访问控制(第11条)和如果他们的班级不是工会.

  • 如果两个指针指向具有不同访问控制的同一对象的非静态数据成员(第11条),则结果未指定.

  • 如果两个指针指向同一个union对象的非静态数据成员,则它们比较相等(转换后void*,如果需要).如果两个指针指向同一数组的元素或超出数组末尾的指针,则指向具有较高下标的对象的指针会比较高.

  • 其他指针比较未指定.

20.8.5p8 对照 [comparision]

对于模板greater,less,greater_equal,和less_equal,对于任何指针类型的专业化产生总订单,即使内置的运营商<,>,<=,>=没有.


那么,标准真正说的是什么?

T * p = new T;
T * q = nullptr;
Run Code Online (Sandbox Code Playgroud)


判决是p < q什么?
因为p并且q没有指向同一个数组的不同元素(包括一个超过数组最后一个元素的元素),并且两者都没有指向同一个对象的非静态数据成员; 在执行p < q(和p > q)时未指定的结果.

bool a = p < q;  // unspecified
bool b = p < q;  // unspecified

assert (a == b); // can fire
Run Code Online (Sandbox Code Playgroud)


怎么样std::less
但是,在使用时,std::less我们保证总订单 - 这实际上意味着下面的断言无法触发(标准-20.8.5p8).

std::less<T*> comp;

bool a = comp (p, q);  // unspecified
bool b = comp (p, q);  // unspecified

assert (a == b);       // can not fire
Run Code Online (Sandbox Code Playgroud)


Mik*_*our 5

不,未指定相对于任何非空指针的空指针的排序.

如果操作数"指向不是同一对象的成员或同一数组的元素或不同的函数,或者只有其中一个为空"的不同对象,则未指定比较运算符的结果.

std::less和朋友们对此进行扩展以指定总订单,但不指定以该顺序出现空指针的位置.所以它保证null将始终大于或小于任何给定的非空指针.但它没有被指定为小于或大于所有非空指针.