Почему это reinterpret_cast не работает в Visual Studio?

У меня есть код (см. Ниже), и, как ни странно, он отлично компилируется, когда я запускаю код через gcc, но когда я открываю тот же файл в Visual Studio 2017, я получаю ошибку компилятора на мелодию:

Error   C2440   'reinterpret_cast': cannot convert from '::size_t' to 'Alias'

Вот минимальный пример, который вы можете попробовать, если хотите. Просто нажмите «новый проект», выберите консольное приложение Windows C ++, вставьте этот код и попробуйте скомпилировать в режиме отладки x86 по умолчанию:

#include "stdafx.h"
#include <cstddef>

typedef std::size_t Alias;

Alias makeAlias(std::size_t n)
{
    return reinterpret_cast<Alias>(n);
}

int main()
{
    std::size_t x = 1;
    Alias t = makeAlias(x);
    return 0;
}

Как ни странно, если вы измените оператор return на этот немного более запутанный вариант, он действительно компилируется, поэтому похоже, что Visual Studio решила разрешить reinterpret_cast только для типов указателей:

return *(reinterpret_cast<Alias*>(&n));

Это кажется мне странным решением Visual Studio, потому что, согласно справке по cpp:

В отличие от static_cast, но, как и const_cast, выражение reinterpret_cast не компилируется ни в какие инструкции ЦП. Это чисто директива компилятора, которая инструктирует компилятор обрабатывать последовательность битов (представление объекта) выражения, как если бы она имела тип new_type.

Так что, по крайней мере, мне кажется, что если я попытаюсь reinterpret_cast между двумя типами, которые занимают память одинаковым образом, то reinterpret_cast действительно будет тем, для чего требуется. В конце концов, я, как следует из названия, «переинтерпретирую» один и тот же битовый шаблон для другого типа.

Я понимаю, что reinterpret_cast в основном нацелен на преобразование между типами указателей, но я не понимаю, почему мне следует запретить использовать его в подобных ситуациях. В своего рода смысле «используйте правильный инструмент для правильной работы», не будет ли разумнее разрешить программистам использовать reinterpret_cast по прямому назначению, вместо того, чтобы заставлять их использовать static_cast, когда в этом нет необходимости (не говоря уже о том, что напрасно прожигает несколько тактов в процессе)?

Есть ли какая-то опасность в разрешении reinterpret_cast между псевдонимами типов, из-за которой Visual Studio запретит это? Reinterpret_cast определенно может быть опасным при неправильном использовании, но я не понимаю, почему он должен давать сбой при правильном использовании (если, конечно, я чего-то не упускаю в определении «правильного» использования в этом случае).


person Scorch    schedule 02.03.2018    source источник
comment
Спасибо за совет, я пошел дальше и отредактировал вопрос   -  person Scorch    schedule 02.03.2018
comment
Вы остановили вторую половину сообщения об ошибке: примечание: преобразование - это допустимое стандартное преобразование, которое может быть выполнено неявно или с помощью static_cast, преобразования в стиле C или преобразования в стиле функции.   -  person 1201ProgramAlarm    schedule 02.03.2018
comment
FWIW это не имеет ничего общего с решениями, инструкциями процессора или занимаемой памятью. Речь идет об ошибках и семантике (или ее отсутствии)   -  person Lightness Races in Orbit    schedule 02.03.2018
comment
Кстати, отредактированный MCVE отличный - вы, вероятно, можете пойти дальше и удалить старую версию, поскольку она только мешает   -  person Lightness Races in Orbit    schedule 02.03.2018
comment
Замечательно, что лучше. В общем, хорошая работа с этим вопросом и с последующим (к сожалению, очень редко для пользователей с низкой репутацией). Вы далеко пойдете здесь :)   -  person Lightness Races in Orbit    schedule 02.03.2018
comment
@LightnessRacesinOrbit Я случайно отредактировал свой предыдущий комментарий вместо добавления нового. Позвольте мне попробовать еще раз: я изо всех сил пытаюсь найти какой-либо вариант использования, позволяющий переинтерпретировать приведение к тому же типу для интегральных типов, и я также не вижу, куда идет OP с ним (поскольку код был бы неправильным, если бы makeAlias был изменен для использования других типов, не являющихся указателями / ссылками, чем то, что у него есть)   -  person M.M    schedule 02.03.2018
comment
@ M.M: Ну, есть ли вариант использования для этого - совсем другой вопрос (лично я не вижу смысла в его запрете, и вы можете получить некоторую выгоду, когда операнды в шаблоне несколько T1 и T2).   -  person Lightness Races in Orbit    schedule 02.03.2018
comment
Я полагаю, это можно было бы использовать как способ сгенерировать ошибку компиляции, если Alias было изменено на что-то другое, кроме size_t или typedef для того же типа   -  person M.M    schedule 02.03.2018


Ответы (1)


[C++14: 5.2.10/2]: Оператор reinterpret_cast не должен отбрасывать постоянство (5.2.11). Выражение целочисленного типа, типа перечисления, указателя или указателя на член может быть явно преобразовано в его собственный тип; такое приведение дает значение своего операнда.

Поскольку std::size_t является интегральным типом, а Alias std::size_t, я бы сказал, что это забавная ошибка Visual Studio.

person Lightness Races in Orbit    schedule 02.03.2018
comment
В основном это сводится к следующему: reinterpret_cast<int>(1); что вызывает ошибку в VS - person Killzone Kid; 02.03.2018
comment
@KillzoneKid: Совершенно верно. - person Lightness Races in Orbit; 02.03.2018
comment
Подожди, я в замешательстве. Это ошибка VS? Репликация в VS 2019. Говорит ли стандарт, что reinterpret_cast ‹int› (1) не должен компилироваться? Как еще можно переосмыслить битовую последовательность? - person Tyson Hilmer; 16.09.2019