C ++ 20 bit_cast против reinterpret_cast - PullRequest
0 голосов
/ 21 ноября 2018

Согласно последнему заседанию комитета ISO C ++, bit-cast будет представлен в стандарте C ++ 20.

Я знаю, что reinterpret_cast не подходит для этогоработа из-за правил псевдонимов типов , но мой вопрос заключается в том, почему они решили не расширять reinterpret_cast для обработки объекта как представления последовательности битов и предпочли предоставить эту функциональность как новую языковую конструкцию?

Ответы [ 2 ]

0 голосов
/ 23 мая 2019

Существует фундаментальное несоответствие между языковой природой высокого уровня современной строгой интерпретации стандартов языка C и C ++ компиляторами и представлением о том, что вы можете использовать reinterpret_cast, чтобы переосмыслить группу байтов как другие объекты.Обратите внимание, что так называемое правило "строгого псевдонима" в большинстве случаев даже не может использоваться для дисквалификации любых попыток реинтерпретации байтов, так как код не определил бы поведение в первую очередь: reinterpret_cast<float*>(&Int) даже не указатель на число с плавающей точкойобъект, это указатель на целое число, которое имеет неправильный тип.Вы не можете разыменовать его, поскольку в этом месте не создан объект с плавающей точкой;если бы он был, его жизнь не началась бы;и если бы его время жизни началось, он был бы неинициализирован.

Байты, которые, как оказалось, представляют действительный битовый шаблон с плавающей запятой, просто не могут быть интерпретированы как таковые, если у вас нет подходящего объекта с плавающей запятой здесь.

Действительный ненулевой указатель - это не просто типизированное значение начального адреса области, которая оказывается правильно выровненной; недопустимый недействительный указатель указывает на конкретный объект (или один конец конца массива или тривиальный «массив» одного объекта).

Я даже не вижу "строгое псевдонимы "санкционированные скалярные реинтерпретации приводят (как микс со знаком / без знака) как возможно допустимый, поскольку целочисленный объект без знака (соответственно без знака) существует по этому адресу (и компилятор, очевидно, также не может использовать исходное значение без знака (соответственно со знаком)).

В любом случае, C ++ имеет неправильный дизайн, потому что он представляет собой смесь разных языков (некоторые очень низкого уровня, некоторые очень высокого уровня) и сильно сломан.

0 голосов
/ 21 ноября 2018

Ну, есть одна очевидная причина: потому что он не будет делать все, что bit_cast делает.Даже в мире C ++ 20, где мы можем выделить память во время компиляции, reinterpret_cast запрещено в constexpr функциях.Одна из явных целей bit_cast состоит в том, чтобы иметь возможность делать такие вещи во время компиляции:

Кроме того, в настоящее время невозможно реализовать функцию constexpr преобразования битов,поскольку memcpy само по себе не является constexpr.Пометка предложенной функции как constexpr не требует или не предотвращает превращение memcpy в constexpr, но требует поддержки компилятора.Это позволяет реализациям свободно использовать свое собственное внутреннее решение (например, LLVM имеет опкод bitcast).

Теперь вы можете сказать, что можете просто расширить это конкретное использование reinterpret_cast до * 1019.* контексты.Но это усложняет правила.Вместо того, чтобы просто знать, что reinterpret_cast нельзя использовать в constexpr периоде кода, вы должны помнить конкретные формы reinterpret_cast, которые нельзя использовать.

Кроме того, существуют практические проблемы,Даже если вы хотите пойти по маршруту reinterpret_cast, std::bit_cast - это библиотечная функция.И всегда легче получить библиотечную функцию через комитет, чем языковую, даже если она получит некоторую поддержку компилятора.

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

Действительно, если вы произнесете их одинаково, возникает вопрос о том, почему это разумночетко определены:

float f = 20.4f;
int i = reinterpret_cast<int>(f);

Но это как-то плохо:

float f = 20.4f;
int &i = reinterpret_cast<int &>(f);

И конечно, языковой адвокат или кто-то, знакомый со строгим правилом алиасинга, поймет, почему последнее плохо.Но для непрофессионала, если для преобразования битов нормально использовать reinterpret_cast, неясно, почему неправильно использовать reinterpret_cast для преобразования указателей / ссылок и интерпретации существующего объекта как преобразованного типа.

Различные инструменты должны быть написаны по-разному.

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