58
задан 25 January 2019 в 12:20

1 ответ

TL; DR:

  • в C++ 98/03 пункт не присутствовал, и стандарт не указывал операторы отношения для void указатели (базовый выпуск 879, посмотрите конец этого сообщения);
  • нечетный пункт о сравнении void указатели были добавлены в C++ 11 для разрешения его, но это в свою очередь дало начало двум другим проблемам ядра 583 & 1512 (см. ниже);
  • разрешение этих проблем потребовало, чтобы пункт был удален, и заменяется формулировкой, найденной в C++ 14 стандартов, которые допускают "нормальный" void * сравнение.
<час>

Базовый Выпуск 583: Реляционные сравнения указателя с нулевым указателем, постоянным

  1. Реляционные сравнения указателя с нулевым указателем постоянный Раздел: 8,9 [expr.rel]

В C, это плохо формируется (cf C99 6.5.8):

void f(char* s) {
    if (s < 0) { }
} ...but in C++, it's not. Why? Who would ever need to write (s > 0) when they could just as well write (s != 0)?

Это было на языке начиная с ARM (и возможно ранее); по-видимому, это - потому что преобразования указателя (7.11 [conv.ptr]) должны быть выполнены на обоих операндах каждый раз, когда один из операндов имеет тип указателя. Таким образом, похоже, что "null-ptr-to-real-pointer-type" преобразование цепляет поездку с другими преобразованиями указателя.

Предложенное разрешение (апрель 2013):

Этот вопрос решен разрешением [1 151] Выпуск 1512 Ядра выпуска 1512 .

: сравнение Указателя по сравнению с преобразованиями квалификации

  1. сравнение Указателя по сравнению с Разделом преобразований квалификации: 8,9 [expr.rel]

Согласно 8,9 [expr.rel] абзацам 2, описывая сравнения указателя,

преобразования Указателя (7.11 [conv.ptr]) и преобразования квалификации (7.5 [conv.qual]) выполняются на операндах указателя (или на операнде указателя и постоянном нулевом указателе, или на двух константах нулевого указателя, по крайней мере одна из которых является неинтегралом) принести им к их составному типу указателя. Это, казалось бы, сделало бы следующий пример плохо сформированным,

 bool foo(int** x, const int** y) {
 return x < y;  // valid ?   } because int** cannot be converted to const int**, according to the rules of 7.5 [conv.qual] paragraph 4.

Это кажется слишком строгим для сравнения указателя, и текущие реализации принимают пример.

Предложенное разрешение (ноябрь 2012):

<час>

Соответствующие выборки от [1 152] разрешение вышеупомянутых проблем найдены в газете: сравнение Указателя по сравнению с преобразованиями квалификации (пересмотр 3) .

следующее также разрешает ядро Изменение выпуска 583 .

в 5,9 expr.rel абзацах 1 - 5:

В этом разделе следующее утверждение ( нечетный пункт в C++ 11 ) было , вычеркнул :

Указатели на void (после преобразований указателя) могут быть сравнены с результатом, определенным следующим образом: Если оба указателя представляют тот же адрес или являются оба значением нулевого указателя, результат true, если оператор <= или >= и false иначе; иначе результат неуказанный

, И следующие утверждения были , добавил :

  • , Если два указателя указывают на различные элементы того же массива, или к подобъектам этого, указатель на элемент с более высоким нижним индексом выдерживает сравнение больше.
  • , Если один указатель указывает на элемент массива, или к подобъекту этого, и другой указатель указывает на одно прошлое последний элемент массива, последний указатель выдерживает сравнение больше.

Так в заключительном рабочем проекте C++ 14 (n4140) раздел [expr.rel]/3, вышеупомянутые операторы найдены, поскольку они были указаны во время разрешения.

<час>

Рытье по причине, почему этот нечетный пункт был добавлен, привело меня к намного более раннему выпуску 879: Недостающие встроенные операторы сравнения для типов указателей . Предложенное разрешение этой проблемы (в июле 2009) ведомый к добавлению этого пункта, который был выбран в WP в октябре 2009.

И именно так это стало включенным в C++ 11 стандартов.

36
ответ дан 1 November 2019 в 15:06

Другие вопросы по тегам:

Похожие вопросы: