динамическая путаница - PullRequest
       7

динамическая путаница

10 голосов
/ 17 ноября 2010

Я отказываюсь от этого ...

$ 5.2.7 / 2- "Если T является типом указателя, v должно быть r-значением указателя на полный тип класса и результатявляется r-значением типа T. Если T является ссылочным типом, v должно быть l-значением полного класса, а результатом является l-значение типа, на который ссылается T. "

InВ соответствии с вышесказанным, следующий код должен быть правильно сформирован.

struct A{};
struct B : A{};

int main(){
   B b;
   A a, &ar1 = b;

   B& rb1 = dynamic_cast<B&>(ar1);  // Does not $5.2.7/2 apply here?
   B& rb2 = dynamic_cast<B&>(a);    // and also here?
}

Но это не так.Все компиляторы жалуются на то, что операнд к dynamic_cast не является полиморфным в соответствии с

$ 5.2.7 / 6. В противном случае v должен быть указателем или значением l полиморфного типа (10.3).

Итак, мой вопрос: что означает $ 5.2.7 / 2?Почему $ 5.2.7 / 6 здесь?

Ответы [ 3 ]

9 голосов
/ 17 ноября 2010

Ну, все требования в 5.2.7 должны соблюдаться вместе .Вы не можете просто остановиться после 5.2.7 / 2 и начать писать код, который якобы удовлетворяет всем «до 5.2.7 / 2».В п. 5.2.7 определена спецификация dynamic_cast.

. Выделяется полиморфное требование, поскольку оно условно .Когда вы используете dynamic_cast для upcasts, полиморфное требование не применяется (на самом деле, dynamic_cast эквивалентно static_cast в upcasts).Полиморфное требование применяется только в том случае, если вы используете dynamic_cast для нисходящих или перекрестных трансляций.

Спецификация dynamic_cast организована последовательно, что означает, что она сначала заботится о более простых случаях, а затем переходит к более сложным приложениям.Вы должны читать его шаг за шагом, пока он не охватит вашу конкретную ситуацию.Все, что вы читаете по этому пути, накапливается, и «иначе» означает: «если мы еще не рассмотрели ваше дело, тогда продолжайте чтение».

4 голосов
/ 17 ноября 2010

Чтобы сделать понижение , как в вашем примере, структура А должна быть полиморфной и иметь RTTI. Вот скорректированная версия, которая работает, в точку:

struct A{virtual void f(){}};
struct B : A{};

int main(){
   B b;
   A a, &ar1 = b;

   B& rb1 = dynamic_cast<B&>(ar1);  // Does not $5.2.7/2 apply here?
   //B& rb2 = dynamic_cast<B&>(a);    // and also here?
}

При добавлении виртуальной формы, делающей ее полиморфной, RTTI включается для класса, что позволяет понижать рейтинг.

Обратите внимание, что ваш второй пример не может работать - поскольку вы преобразуете модуль (a) в ссылку на модуль - что не разрешено.


Обновление:

Ваш код не разрешен в соответствии с 5.2.7.5 и не разрешен в соответствии с 5.2.7.6. Моя настройка заставляет его работать под 5.2.7.6

3 голосов
/ 17 ноября 2010

«В противном случае» в данном случае означает «если не применяются условия в 5.2.7 / 5».

Вы можете сказать это, потому что / 2 накладывает на программу требование относительно операнда dynamic_cast (обратите внимание, что «должен» язык «v будет lvalue» против «is» язык «результат является lvalue»).Как и в других местах в стандарте, выражение требования не обязательно означает, что это требование only .В других пунктах могут быть указаны дополнительные требования.В этом случае / 6 устанавливает дополнительное требование, которое применяется только в определенных случаях, в зависимости от T и статического типа v.

/ 3, / 4, / 5 сообщают вам о значении результата, и они полностью соответствуют требованию в / 2.Ни один из них не начинается с «В противном случае».Поэтому для меня совершенно очевидно, что они не образуют цепочку «иначе, если», начинающуюся с /2.

Некоторые скобки или что-то может сделать это более понятным (то есть, что «в противном случае» в / 6 относится к «если "в / 5, а не" если "в / 2, / 3 или / 4).Но это просто не стиль дома.

Помимо всего прочего, «иначе» в / 5 логически не может значимо применяться к условиям в / 2./ 1 говорит, что T должен быть «указатель или ссылка на полный тип класса, или cv void*»./ 2 охватывает два случая - типы указателей и ссылочные типы.Это все«/ Иначе» в / 2 не существует (если не сказать «иначе, соответствующий компилятор должен выдать диагностику», но это неявно)

...