Всегда ли выполняется утверждение в следующем фрагменте кода?
std::less<Object *> lessPtr;
Object * o = new Object();
assert(lessPtr (o, nullptr) == false);
Всегда ли выполняется утверждение в следующем фрагменте кода?
std::less<Object *> lessPtr;
Object * o = new Object();
assert(lessPtr (o, nullptr) == false);
Этот вопрос действительно сводится к тому, что использование менее реляционного оператора по типам указателей, где один операнд является nullptr
, даст ожидаемый результат; что, к сожалению, не так.
Результат не указан.
Примечание: Имейте в виду, что
std::less
гарантирует общий порядок; что даже если результат при использовании объекта функции не задан, он должен давать то же самое неуказанное значение для каждого вызова.
5.9p2 Реляционные операторы
[expr.rel]
Указатели на объекты или функции одного и того же типа (после конверсий указателей) можно сравнить с результатом, определяемым следующим образом:
Если два указателя
p
иq
того же типа указывают на один и тот же объект или функцию, либо оба указывают один за концом одного и того же массива, либо оба являются нулевыми, тоp<=q
иp>=q
оба выходаtrue
иp<q
иp>q
даютfalse
.Если два указателя
p
иq
того же типа указывают на разные объекты, которые не являются членами одного и того же объекта или элементов одного и того же массива или с разными функциями, или если только один из них null, результатыp<q
,p>q
,p<=q
иp>=q
не определены.Если два указателя указывают на нестатические элементы данных одного и того же объекта или на подобъекты или элементы массива таких элементов, рекурсивно, указатель на более поздний объявленный элемент сравнивается больше, если два члена имеют одинаковый доступ (раздел 11) и при условии, что их класс не является объединением.
Если два указателя указывают на нестатические элементы данных одного и того же объекта с различным контролем доступа (раздел 11), результат не указан.
Если два указателя указывают на нестатические элементы данных одного и того же объекта объединения, они сравнивают одинаковые значения (после преобразования в
void*
, если необходимо). Если два указателя указывают на элементы одного массива или один за концом массива, указатель на объект с более высоким индексом сравнивается выше.Другие сравнения указателей не указаны.
20.8.5p8
Сравнение[comparision]
Для шаблонов
greater
,less
,greater_equal
иless_equal
специализации для любого типа указателя дают полный порядок, даже если встроенные операторы<
,>
,<=
,>=
не.
T * p = new T;
T * q = nullptr;
Каков вердикт для p < q
?
Поскольку p
и q
не указывают на разные элементы одного и того же массива (включая элемент один за последним элементом массива), и оба не указывают на нестатические элементы данных одного и того же объекта; результат при выполнении p < q
(и p > q
) не указан.
bool a = p < q; // unspecified
bool b = p < q; // unspecified
assert (a == b); // can fire
Как насчет std::less
?
Однако при использовании std::less
нам гарантируется полный порядок, что фактически означает, что нижеприведенное утверждение не может fire (standard-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
Нет, порядок нулевого указателя относительно любого ненулевого указателя не указан.
Результат операторов сравнения не указан, если операнды "указывают на разные объекты, которые не являются членами одного и того же объекта или элементов одного и того же массива или с разными функциями, или если только один из них является нулевым".
std::less
и друзья расширяют это, чтобы указать, что существует общий порядок, но не указывать, где в этом порядке присутствуют нулевые указатели. Таким образом, он гарантировал, что null
будет последовательно либо больше, либо меньше любого заданного непустого указателя. Но он не указан как меньше или больше, чем все ненулевые указатели.