Здравствуйте, Alexander G, Вы писали:
AG>Чтобы делать безопасные reinterpret_cast'ы с последующим доступом через результат каста.
Ну, давайте посмотрим на перечень этих самых "безопасных" преобразований из U* в T* (будем считать, что со ссылками дела обстоят аналогично).
1) T и U — типы, которые, возможно, отличаются лишь cv-квалификацией. Очень ценное применение reinterpret_cast
2) T — это char или unsigned char (странно, что в 3.10/15 отсутствует signed char — IMHO, баг стандарта)
3) T и U — интегральные типы, различающиеся в знаковости.
Довольно скромный перечень, однако. Для последнего вида преобразований я предпочитаю использовать отдельную функцию signed_cast. Во-первых, код более понятен, во-вторых, пресекается возможность нежелательных преобразований вроде wchar_t* -> unsigned char* (вместо char* -> unsigned char*, как задумывалось) или unsigned char* -> wchar_t. alias_pointer_cast в данном случае не пресекает часть очевидно нежелательных преобразований и с точки зрения самодокументируемости код практически не улучшает.
Что происходит, когда какой-то из типов оказывается bool или wchar_t, — это отдельная история
Итак, из потенциально полезных остаётся преобразование (2). Что же проще запомнить: что reinterpret cast в указатель на char / signed char / unsigned char действительно "безопасен" или что alias_pointer_cast — это разновидность "безопасного" reinterpret cast?
Конечно, тут можно возразить, что эта конструкция может использовать в каком-нибудь шаблоне, где заранее может быть неизвестно, какой вид преобразования (1-й, 2-й или 3-й) потребуется. Интересно, как часто возникает такая ситуация?
...
M>Стандарт гарантирует, что pn будет указывать на x.n, а px — на x. Применим ли тут где-либо вышеописанный alias_pointer_cast?
Нет. Но остальные варианты из 3.10/15 можно покрыть.
Насчёт этого
- an aggregate or union type that includes one of the aforementioned types among its members (including,
recursively, a member of a subaggregate or contained union),
можно было бы добавить версию с ослабленой проверкой, которая бы в случае pod composite с любой из сторон выполняла бы приведение.
Здравствуйте, Alexander G, Вы писали:
AG>Но остальные варианты из 3.10/15 можно покрыть.
Тут есть ещё минимум одна проблема: к базовому подобъекту в общем случае нельзя обращаться через lvalue/указатель, полученный reinterpret cast-ом над lvalue/указателем_на_объект производного класса.
Здравствуйте, Masterkent, Вы писали:
M>Тут есть ещё минимум одна проблема: к базовому подобъекту в общем случае нельзя обращаться через lvalue/указатель, полученный reinterpret cast-ом над lvalue/указателем_на_объект производного класса. M>Так всё же зачем может понадобиться такой шаблон?
Наверное, чтобы компилятор не имел права игнорировать ++*(X*)(T*)&x?