Ответ 1
Это выглядит как ошибка MSVC. Стандарт проекта С++ 14 явно позволяет добавлять и вычитать значение 0
в указатель для сравнения, равный самому себе, из [expr.add] p7:
Если значение 0 добавляется или вычитается из значения указателя, результат сравнивается с исходным значением указателя. Если два указателя указывают на один и тот же объект или обе точки за концом одного и того же массива, либо оба равны нулю, а два указателя вычитаются, результат сравнивается с значением 0, преобразованным в тип std :: ptrdiff_t.
Похоже, что дефект CGG 1776 приводит к p0137, который скорректировал [expr.add] p7, чтобы явно указать null pointer
.
Последний проект сделал это еще более явным [expr.add] p4:
Когда выражение J, которое имеет интегральный тип, добавляется или вычитается из выражения P типа указателя, результат имеет тип P.
- Если P оценивает значение нулевого указателя, а J оценивается как 0, результатом является значение нулевого указателя.
- В противном случае, если P указывает на элемент x [i] объекта массива x с n элементами 85, выражения P + J и J + P (где J имеет значение j) указывают на (возможно, гипотетический) элемент x [ я + j], если 0≤i + j≤n, а выражение P - J указывает на (возможно, гипотетический) элемент x [i-j], если 0≤i-j≤n. (4.3).
- В противном случае поведение не определено.
Это изменение было внесено в редакцию, чтобы увидеть эту проблему github и этот PR.
MSVC здесь несовместим в том смысле, что он позволяет добавлять и вычитать нуль в постоянном выражении точно так же, как gcc и clang. Это важно, потому что неопределенное поведение в постоянном выражении плохо сформировано и поэтому требует диагностики. Учитывая следующее:
constexpr int *p = nullptr ;
constexpr int z = 0 ;
constexpr int *q1 = p + z;
constexpr int *q2 = p - z;
gcc, clang и MSVC позволяют это постоянное выражение (пример livebobbtt), хотя, к сожалению, MSVC вдвойне непоследовательна в том, что он также позволяет отличать ненулевое значение, учитывая следующее:
constexpr int *p = nullptr ;
constexpr int z = 1 ;
constexpr int *q1 = p + z;
constexpr int *q2 = p - z;
как clang, так и gcc говорят, что он плохо сформирован, в то время как MSVC не живет (живет godbolt).