質問: sizeof(From)) && std::is_trivially_copyable::value && std::is_trivial::value, // この実装は To がトリビアルにデフォルト構築可能であることを要求します。 To>::type // constexpr のサポートはコンパイラマジックが必要です。 bit_cast(const From &src) noexcept { To dst; std::memcpy(&dst, &src, sizeof(To)); return dst; } ``` が掲載されていました。こちらのコードには`std::aligned_storage`が使われていないようです。 ### 教えていただきたいこと 1. `std::aligned_storage`を用いる方法とそうでない方法で、どのような違いがあるか 2. c++17以前で`std::bit_cast`のようなtype punningを行うとき、変換前後の型が整数型、浮動小数点型に限られる場合、constexprにこれを行う方法があるか よろしくおねがいします
回答: > > `std::aligned_storage`を用いる方法とそうでない方法で、どのような違いがあるか > > > 変換先型`To`に対する「デフォルトコンストラクタの要求」有無が異なると思います。より汎用性の高い実装では、デフォルトコンストラクタを必要としない `std::aligned_storage` が必要となります。 cpprefjpの文言は、提案文書 P0476R2 からの引用・翻訳と思われます。原文後半には`aligned_storage`が必要となる理由への言及があります(太字)。 > > Attuned developers use `aligned_storage` with `memcpy`, avoiding alignment pitfalls and **allowing them to bit-cast non-default-constructible types**. > > > 提案者自身による実装例 jfbastien/bit_cast も、下記実装になっています(引用に際して一部簡略化しました): ``` template inline constexpr To bit_cast(const From& from) noexcept { typename std::aligned_storage::type storage; std::memcpy(&storage, &from, sizeof(To)); return reinterpret_cast(storage); // More common implementation: // std::remove_const_t to{}; // std::memcpy(&to, &from, sizeof(To)); // return to; } ``` > > c++17以前でstd::bit_castのようなtype punningを行うとき、変換前後の型が整数型、浮動小数点型に限られる場合、constexprにこれを行う方法があるか > > > C++17標準仕様の範囲内では不可能と思われます。だからこそ `std::bit_cast` 関数が追加されたはずです。C++20でも結局はコンパイラによる特殊サポートが必須となります。(`std::bit_cast`は"コンパイラマジック”関数として実現されます) 提案文書 P0476R2 §1. Backgroundより引用: > > Furthermore, it is currently impossible to implement a `constexpr` bit-cast function, as `memcpy` itself isn't `constexpr`. Marking the proposed function as `constexpr` doesn't require or prevent `memcpy` from becoming `constexpr`, but requires compiler support. This leaves implementations free to use their own internal solution (e.g. LLVM has a bitcast opcode). > > >