static_cast и reinterpret_cast для std::aligned_storage

может кто-нибудь объяснить фрагмент кода о приведении в http://en.cppreference.com/w/cpp/types/aligned_storage пожалуйста?

можно следующий код

return *static_cast<const T*>(static_cast<const void*>(&data[pos]));

заменить на

 return *reinterpret_cast<const T*>(&data[pos]);

?

Почему здесь используются два литья? Большое спасибо.

Хонг


person hong pei    schedule 10.10.2013    source источник
comment
Я подозреваю, что это необходимо для надлежащей переносимости/соответствия стандарту, потому что результат reinterpret_cast не указан в стандарте. На практике они, вероятно, делают одно и то же во всех или почти во всех реализациях.   -  person Steve Jessop    schedule 10.10.2013
comment
Эти два эквивалентны в С++ 11.   -  person Simple    schedule 10.10.2013
comment
@SteveJessop: я думаю, это ответ.   -  person John Dibling    schedule 10.10.2013
comment
@JohnDibling: было бы, если бы я был уверен, что это правильно (во-первых, reinterpret_cast недостаточно указано для задания, а во-вторых, это причина, по которой в примере кода используются эти два приведения). Это немного плохой показатель, если std::aligned_storage действительно дает вам что-то, что в двух шагах от того, чтобы его можно было использовать.   -  person Steve Jessop    schedule 10.10.2013
comment
Сначала я использовал reinterpret_cast в этом примере cppreference, но затем изменил эту цепочку static_cast с комментарием «избегайте формального UB» после прочтения обсуждения Lounge, начиная с chat.stackoverflow.com/transcript/message/10437436#10437436 и пост TR1-age stackoverflow.com /a/1082398/273767 .. но, возможно, я был слишком осторожен. Не стесняйтесь вернуться, если кто-то опубликует убедительный ответ.   -  person Cubbi    schedule 10.10.2013


Ответы (1)


Согласно стандарту (§ 5.2.10 reinterpret_cast, раздел 7):

Указатель на объект может быть явно преобразован в указатель на объект другого типа. Когда значение prvalue v типа «указатель на T1» преобразуется в тип «указатель на cv T2», результатом будет static_cast<cv T2*>(static_cast<cv void*>(v)) если и T1, и T2 являются типами стандартной компоновки, а требования к выравниванию T2 не строже, чем те из T1.

Преобразование значения prvalue типа «указатель на T1» в тип «указатель на T2» (где T1 и T2 являются объектными типами и где требования выравнивания T2 не более строгие, чем требования T1) и обратно в его исходный тип дает исходный значение указателя. Результат любого другого такого преобразования указателя не указан.

Итак, мы можем сделать следующий вывод:

  1. reinterpret_cast<*T>(ptr) эквивалентно static_cast<*T>(static_cast<void*>(ptr))
  2. static_cast<>(ptr) не всегда равно ptr, но reinterpret_cast<>(ptr) всегда равно ptr
  3. если нет проблем с выравниванием, мы можем безопасно использовать reinterpret_cast
person Yury Bayda    schedule 28.10.2013