Почему снижение в CRTP определяет поведение - PullRequest
0 голосов
/ 19 февраля 2019

Я использовал шаблон CRTP некоторое время, однако, читая ответы о неопределенном поведении, связанном с понижением рейтинга, я не понимаю, почему static_cast<Derived&>(this), где this имеет тип Base<Derived>*, это определенное поведение, где Derived публично наследуется от Base<Derived>.

Стандарт совершенно ясен:

static_cast (выражение)

Если new_type является указателем или ссылкой нанекоторый класс D и тип выражения являются указателем или ссылкой на его не виртуальную базу B, static_cast выполняет downcast.Это понижение является неправильным, если B является неоднозначным, недоступным или виртуальным основанием (или основанием виртуального основания) D.

Но, глядя на аналогичные вопросы, C ++ наследование наследования :

Как выполнить приведение из точечного объекта [ Базовый класс ] к объекту подпункта [ Производный класс ]?

Самый рейтинговый ответ:

"Вы не можете; если только у точки [ База ] нет оператора преобразования или подпункта [ Производное ] имеет конструктор преобразования, и в этом случае типы объектов могут быть преобразованы без необходимости приведения. "

Другой пример: родительский класс static_cast для дочернего класса C ++

// B : public A
A a;
B* bptr = static_cast<B*>(&a);

Самый рейтинговый комментарий:

«Это неопределенное поведение».

Но затем говорит:

«Выможет сделать это безопасно, используя CRTP или dynamic_cast. "

Здесь ( C ++ static_cast downcast validity ) это снова упоминается:

Base base{190};
A& a = static_cast<A&>(base);

"Нет [недопустимо], объект типа Base не является объектом типа A [ Производное ]"


Чем отличается downcast в CRTP;почему это не вызывает неопределенное поведение, а случаи выше?Следуя логике ответа выше, не правда ли, что класс Base<Derived> не является объектом типа Derived (обратное утверждение верно), но вы можете использовать static_cast?

ВозможноЯ просто неправильно понимаю CRTP.

1 Ответ

0 голосов
/ 19 февраля 2019

Возвращаясь к первому абзацу:

Если new_type является указателем или ссылкой на некоторый класс D, а тип выражения является указателем или ссылкой на его не виртуальную базу B, static_cast выполняет downcast,Это понижение является неправильным, если B является неоднозначным, недоступным или виртуальным основанием (или основанием виртуального основания) из D.

и включает следующее предложение:

Такой static_cast не проверяет во время выполнения, чтобы гарантировать, что тип времени выполнения объекта действительно D, и может использоваться безопасно только в том случае, если это предварительное условие гарантировано другими средствами, например, при реализации статического полиморфизма.

CRTP использует / - это другое название статического полиморфизма.

Учитывая struct D : B<D>, если B<D> static_cast *this до D&, то это определенное поведение, поскольку указатель this действительно является указателем на D иB<D>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...