Я слышал, что std::bit_cast
будет в C ++ 20, и я немного озадачен выводом о том, что его реализация обязательно требует специальной поддержки компилятора.
Чтобы быть справедливымЯ слышал аргумент, что реализация выполняет операцию memcpy
, и memcpy
обычно не constexpr
, в то время как std::bit_cast
, как предполагается, поэтому для std::bit_cast
constexpr
предположительно требуется поддержка компилятора дляconstexpr
-совместимая memcpy
операция.
Мне было интересно, однако, можно ли реализовать совместимый bit_cast
(т. Е. Определенное поведение в той же степени, что использование memcpy
имело бы определенное поведение) без фактического вызова memcpy
вall.
Рассмотрим следующий код:
template<typename T, typename U>
inline constexpr T bit_cast(const U & x) noexcept {
static_assert(std::is_trivial<T>::value && std::is_trivial<U>::value, "Cannot use bit_cast with non-trivial data" );
static_assert(sizeof(T) == sizeof(U), "bit_cast must be used on identically sized types");
union in_out {
volatile U in;
volatile T out;
inline constexpr explicit in_out(const U &x) noexcept : in(x)
{
}
};
return in_out(in_out(x)).out;
}
Здесь используются энергозависимые элементы, чтобы заставить компилятор выдавать необходимый код, который будет записываться или считываться из элементов, отключая оптимизацию и, в то время какЯ знаю, что обычно присваивание одному члену объединения и чтение из другого в том же объединении является неопределенным поведением, стандарт C ++, по-видимому, позволяет читать из любого члена объединения IF , он был побайтово скопирован из другогоэкземпляр точно такого же союза. В приведенном выше коде это эффективно достигается путем явного вызова конструктора копирования по умолчанию для вновь созданного экземпляра, который инициализирует элемент данных in
. Поскольку вышеприведенное объединение содержит все тривиальные типы, вызов конструктора копирования по умолчанию составляет для него байтовую копию, поэтому чтение из члена out
вновь созданного экземпляра по-прежнему не должно быть неопределенным поведением, не так ли?
Конечно, вполне возможно, что я здесь упускаю что-то чрезвычайно очевидное ... Я, конечно, не могу утверждать, что я умнее людей, которые разрабатывают эти стандарты, но если кто-то может сказать мне, какое именно неопределенное поведение я используюздесь я бы очень хотел узнать об этом.