Код правильный, компилятор не соответствует стандарту, который гласит (раздел [expr.eq]
, используя формулировку из C ++ 0x черновик n3225, но он должен быть таким же в других версиях):
любой указатель на член можно сравнить с константой нулевого указателя
и
Если оба операнда равны нулю, они сравниваются равными.Иначе, если только один равен нулю, они сравниваются неравно.
соответствующее определение константы нулевого указателя (раздел [conv.ptr]
, часть std::nullptr_t
является новой в C ++ 0x):
A константа нулевого указателя - это целочисленное константное выражение (5.19) prvalue целочисленного типа, которое оценивается как ноль, или prvalue типа std::nullptr_t
.
и(раздел [expr.const]
):
Выражение константы - это целочисленное константное выражение, если оно имеет целочисленный или перечислимый тип.
ПРИМЕЧАНИЕ.-определенное представление указателя на функцию-член-виртуал обычно представляет собой индекс в виртуальной таблице, который будет равен 0 в вопросе.Но согласно стандарту, выражение внутри assert не проверяет, является ли представление нулевым, оно проверяет нулевой литерал - это проверка нулевого указателя.
И компилятор Apple, очевидно, смешал двавверх.Если вы хотите проверить, является ли представление нулевым, вы могли бы написать assert((intptr_t)p != 0)
- и это было бы полностью непереносимым.
Но код в том виде, как он написан, совершеннопереносимый на любой совместимый со стандартом компилятор, и никогда не будет утверждать .
РЕДАКТИРОВАТЬ: И еще одна цитата из стандарта, которая просто повторяет то, что мы уже изучили (раздел [conv.mem]
):
Константа нулевого указателя (4.10) может быть преобразована в указатель на тип члена;результатом является значение указателя нулевого элемента этого типа, которое отличается от любого указателя на элемент, не созданный из константы нулевого указателя.