Это поведение описано в [expr.typeid] / 2 (N3936):
Когда typeid
применяется к выражению glvalue, тип которого является полиморфным типом класса, результат относится к объекту std::type_info
, представляющему тип самого производного объекта (то есть динамического типа), к которому относится glvalue относится. Если выражение glvalue получено путем применения к указателю унарного оператора *
, а указатель является нулевым значением указателя, выражение typeid
выдает исключение типа, которое соответствует обработчику типа std::bad_typeid
exception.
Выражение 1 ? *p : *p
всегда является lvalue. Это связано с тем, что *p
является lvalue, а [expr.cond] / 4 говорит, что если второй и третий операнд троичного оператора имеют одинаковые тип и категорию значения, то результат оператора имеет этот тип и категорию значения также.
Следовательно, 1 ? *m_basePtr : *m_basePtr
является lvalue с типом Base
. Поскольку Base
имеет виртуальный деструктор, это полиморфный тип класса.
Следовательно, этот код действительно является примером того, «когда typeid
применяется к выражению glvalue, тип которого является полиморфным типом класса».
Теперь мы можем прочитать остальную часть приведенной выше цитаты. Выражение glvalue было , а не «получено путем применения унарного оператора *
к указателю» - оно было получено через троичный оператор. Следовательно, стандарт не требует создания исключения, если m_basePtr
равно нулю.
Поведение в случае, если m_basePtr
равно нулю, будет охватываться более общими правилами разыменования нулевого указателя (которые на самом деле немного мутны в C ++, но для практических целей мы предположим, что это вызывает неопределенное поведение здесь ).
Наконец: зачем кому-то писать это? Я думаю, что ответ curiousguy является наиболее правдоподобным предложением: с этой конструкцией компилятору не нужно вставлять тест с нулевым указателем и код для генерации исключения так что это микрооптимизация.
Предположительно, программист либо достаточно счастлив, что его никогда не вызовут с нулевым указателем, либо счастлив полагаться на обработку конкретной реализации разыменования нулевого указателя.