Это похоже на ошибку MSVC, проект стандарта C ++ 14 явно разрешает добавление и вычитание значения 0
к указателю для сравнения, равного себе, из [expr.add] p7 :
Если значение 0 добавляется или вычитается из значения указателя, результат сравнивается равным исходному значению указателя.Если два указателя указывают на один и тот же объект или оба указывают один за концом одного и того же массива или оба равны нулю, и оба указателя вычитаются, результат сравнивается равным значению 0, преобразованному в тип std :: ptrdiff_t.
Похоже, дефект CWG 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 [i + 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 допускают постоянное выражение ( пример с живым крестиком ), хотя, к сожалению, MSVC вдвойне несовместим в том, что допускает также ненулевое значениес учетом следующего:
constexpr int *p = nullptr ;
constexpr int z = 1 ;
constexpr int *q1 = p + z;
constexpr int *q2 = p - z;
и clang, и gcc говорят, что он плохо сформирован, в то время как MSVC этого не делает ( live godbolt ).