Этот вопрос вдохновлен комментариями здесь.
Рассмотрим следующий фрагмент кода:
struct X {}; // no virtual members
struct Y : X {}; // may or may not have virtual members, doesn't matter
Y* func(X* x) { return dynamic_cast<Y*>(x); }
Несколько человек предложили, чтобы их компилятор отклонил тело func.
Однако мне кажется, что независимо от того, определяется ли это стандартом, зависит от времени выполнения x. Из раздела 5.2.7 ([expr.dynamic.cast]):
Результат выражения
dynamic_cast<T>(v)является результатом преобразуя выражениеvв типT.Tдолжен быть указателем или ссылку на полный тип класса или "указатель на cvvoid". Операторdynamic_castне должен отбрасывать константу.Если
T- тип указателя,vдолжен быть prvalue указателя на полный класс type, а результатом является значение типаT. ЕслиT- значение l ссылочный типvдолжен быть lvalue полного типа класса, а результатом является l-значение типа, обозначаемогоT. ЕслиT- значение r ссылочный типvдолжен быть выражением, имеющим полный тип класса, и результатом является x значение типа, на которое указываетT.Если тип
vсовпадает сT, или он совпадает сT, за исключением того, что тип объекта класса вTбольше CV, чем тип объекта класса вvрезультатv(при необходимости преобразуется).Если значение
vявляется значением нулевого указателя в случае указателя, результатом является значение нулевого указателя типаT.Если T является "указателем на cv1
B" иvимеет тип 'указатель на cv2D", так чтоBявляется базовым классомD, результатом является указатель на уникальный объектBобъектаD, на который указываетv. Аналогично, если T является" ссылкой на cv1B" иvимеет тип cv2Dтакой, чтоBявляется базовым классомD, результатом является единственный подобъектBDобъект, на который ссылаетсяv. Результатом является lvalue, еслиT- значение lvalue reference или xvalue, еслиTявляется ссылкой rvalue. Как в указатель и справочные случаи, программа плохо сформирована, если cv2 имеет более высокая cv-квалификация, чем cv1, или еслиBявляется недоступным или неоднозначный базовый классD.В противном случае
vдолжен быть указателем на или значением полиморфного типа.Если
T"указатель на cvvoid", то результатом является указатель на наиболее производные объект, на который указываетv. В противном случае применяется проверка времени выполнения для просмотра если объект, указанный или обозначенныйv, может быть преобразован в тип указана или упомянутаT.) Самый производный объект указал или ссылается наv, может содержать другие объектыBв качестве базовых классов, но они игнорируются.Если
C- тип класса, к которому указывает или ссылаетсяTпроверка выполнения выполняется логически следующим образом:
Если, в большинстве случаев производный объект, на который указывает (обозначается) на
v,vуказывает (ссылается) наpublicподобъект базового класса объектаC, и если только один объект типCвыводится из подобъекта, на который указывает (называется), наv(указывает) на этот объектC.В противном случае, если
vуказывает (ссылается) на подбобку базового классаpublicсамого производного объекта, и тип самого производного объекта имеет базовый класс, типC, это однозначно иpublic, точки результата (относится) кCподобъектом самого производного объекта.В противном случае проверка времени выполнения выходит из строя.
Значение неудачного нажатия на тип указателя является нулевым значение указателя требуемого типа результата. Неудачное приведение к ссылке type throws
std::bad_cast.
Как я читал это, требование полиморфного типа применяется только в том случае, если ни одно из вышеперечисленных условий не выполняется, и одно из этих условий зависит от значения времени выполнения.
Конечно, в некоторых случаях компилятор может положительно определить, что вход не может быть должным образом NULL (например, когда это указатель this), но я все же думаю, что компилятор не может отклонить код, если он не может определить что утверждение будет достигнуто (обычно это вопрос времени выполнения).
Конечно, здесь важна диагностическая диагностика, но совместимо ли это стандартное для компилятора отклонение этого кода с ошибкой?