彼の最近の講演で 「Type C punning in modern C++」 Timur Doumler said そのstd::bit_cast
を使用してfloat
をunsigned char[4]
にビットキャストすることはできません関数から配列を返すことはできません。 std::memcpy
を使用するか、reinterpret_cast<unsigned char*>(&f)[i]
のようなものが明確になるC++ 23(またはそれ以降)まで待つ必要があります。
C++ 20では、std::array
をstd::bit_cast
とともに使用できますか、
float f = /* some value */;
auto bits = std::bit_cast<std::array<unsigned char, sizeof(float)>>(f);
cスタイルの配列の代わりにfloat
?
はい、これはすべての主要なコンパイラで動作します。標準を見てもわかる限り、移植性があり、動作することが保証されています。
まず、std::array<unsigned char, sizeof(float)>
は、集合体であることが保証されています( https://eel.is/c++draft/array#overview-2 )。これは、内部にsizeof(float)
数のchar
sを正確に保持することを示しています(通常、char[]
として)。標準ではこの特定の実装は必須ではありませんが、要素は隣接している必要があります)。追加の非静的メンバーを持つことはできません。
したがって、簡単にコピーでき、そのサイズもfloat
のサイズと一致します。
これらの2つのプロパティを使用すると、それらの間でbit_cast
を実行できます。
[array]/1- ごと:
ヘッダー_
<array>
_は、オブジェクトの固定サイズのシーケンスを格納するためのクラステンプレートを定義します。配列は連続したコンテナです。 _array<T, N>
_のインスタンスは、タイプN
のT
要素を格納するため、size() == N
は不変です。配列は、型を
N
に変換できるT
要素まででリスト初期化できる集約です。配列は、コンテナーおよびリバーシブルコンテナー(_
[container.requirements]
_)のすべての要件を満たしていますが、デフォルトで作成された配列オブジェクトは空ではなく、スワップは複雑ではありません。配列は、シーケンスコンテナーの要件のいくつかを満たしています。ここでは、これらの表のいずれにも記載されていない配列の操作と、追加のセマンティック情報がある操作についてのみ説明します。
標準では、実際には_std::array
_が_T[N]
_型のパブリックデータメンバーを1つだけ持つ必要はないため、理論的にはsizeof(To) != sizeof(From)
または_is_trivially_copyable_v<To>
_が可能です。
これが実際に機能しない場合は、私は驚きます。
はい。
_std::bit_cast
_の動作を説明する paper とその 提案された実装 によると、両方のタイプが同じサイズであり、簡単にコピーできる限り、キャストは成功した。
_std::bit_cast
_の簡略化された実装は、次のようになります。
_template <class Dest, class Source>
inline Dest bit_cast(Source const &source) {
static_assert(sizeof(Dest) == sizeof(Source));
static_assert(std::is_trivially_copyable<Dest>::value);
static_assert(std::is_trivially_copyable<Source>::value);
Dest dest;
std::memcpy(&dest, &source, sizeof(dest));
return dest;
}
_
Float(4バイト)およびsize_of(float)
を含む_unsigned char
_の配列は、これらすべてのアサートを尊重するため、基礎となる_std::memcpy
_が実行されます。したがって、結果の配列の各要素は、floatの1つの連続したバイトになります。
この動作を証明するために、コンパイラエクスプローラーで小さな例を書いて、ここで試すことができます: https://godbolt.org/z/4G21zS 。浮動小数点数5.0は、その浮動小数点数の16進表現 ビッグエンディアン に対応するバイトの配列(_Ox40a00000
_)として適切に格納されます。