名稱空間
變體
操作

std::bit_cast

來自 cppreference.com
< cpp‎ | numeric
 
 
 
位操作
bit_cast
(C++20)
(C++23)
2 的整數次冪
(C++20)
(C++20)
(C++20)
旋轉
(C++20)
(C++20)
計數
(C++20)
(C++20)
(C++20)
位元組序
(C++20)
 
定義於標頭檔案 <bit>
template< class To, class From >
constexpr To bit_cast( const From& from ) noexcept;
(C++20 起)

透過重新解釋 From 的物件表示來獲取 To 型別的值。返回的 To 物件的值表示中的每個位都等於 from物件表示中對應的位。返回的 To 物件中填充位的取值是未指定的。

如果不存在與所生成的值表示對應的 To 型別的值,則行為未定義。如果存在多個此類值,則生成哪個值是未指定的。

如果結果值表示中的位為不確定,則它:

  • 不對應於 From 的值表示中的位(即它對應於一個填充位),或
  • 對應於(直到 C++26)的最小包圍物件(從 C++26 開始)不在其生命週期內的物件的位,或
  • 具有不確定值

如果結果值表示中的位為錯誤,則它對應於其最小包圍物件具有錯誤值的位。

(C++26 起)


否則,結果不包含任何不確定或錯誤值。

對於結果值表示中每個不確定的位,包含該位的最小物件具有不確定值;除非該物件是未初始化友好型別,否則行為未定義。

否則,結果不包含任何不確定值。

(直到 C++26)

對於結果值表示中每個不確定或錯誤的位b,令u為包圍b的最小物件

  • 如果u未初始化友好型別,則如果其值表示中的任何位是不確定的,則u具有不確定值,否則具有錯誤值。
  • 否則,如果b是不確定的,則行為未定義。
  • 否則,行為是錯誤的,結果如上所述。
(C++26 起)

此過載僅在 sizeof(To) == sizeof(From)ToFrom 都是TriviallyCopyable 型別時才參與過載決議。

當且僅當 ToFrom 以及 ToFrom 的所有子物件的型別都滿足以下條件時,此函式模板才為 constexpr

  • 不是聯合型別;
  • 不是指標型別;
  • 不是指向成員的指標型別;
  • 不是 volatile 限定型別;且
  • 沒有引用型別的非靜態資料成員。

目錄

[編輯] 引數

from - 返回值的位源

[編輯] 返回值

一個 To 型別的物件,其值表示如上所述。

[編輯] 可能實現

要實現 std::bit_cast,忽略它是 constexpr 的事實,當需要將物件表示解釋為另一種型別時,可以使用 std::memcpy

template<class To, class From>
std::enable_if_t<
    sizeof(To) == sizeof(From) &&
    std::is_trivially_copyable_v<From> &&
    std::is_trivially_copyable_v<To>,
    To>
// constexpr support needs compiler magic
bit_cast(const From& src) noexcept
{
    static_assert(std::is_trivially_constructible_v<To>,
        "This implementation additionally requires "
        "destination type to be trivially constructible");
 
    To dst;
    std::memcpy(&dst, &src, sizeof(To));
    return dst;
}

[編輯] 注意

在大多數情況下,不應使用 reinterpret_cast(或等效的顯式轉換)在指標或引用型別之間重新解釋物件表示,因為存在類型別名規則

特性測試 標準 特性
__cpp_lib_bit_cast 201806L (C++20) std::bit_cast

[編輯] 示例

#include <bit>
#include <cstdint>
#include <iostream>
 
constexpr double f64v = 19880124.0; 
constexpr auto u64v = std::bit_cast<std::uint64_t>(f64v);
static_assert(std::bit_cast<double>(u64v) == f64v); // round-trip
 
constexpr std::uint64_t u64v2 = 0x3fe9000000000000ull;
constexpr auto f64v2 = std::bit_cast<double>(u64v2);
static_assert(std::bit_cast<std::uint64_t>(f64v2) == u64v2); // round-trip
 
int main()
{
    std::cout
        << "std::bit_cast<std::uint64_t>(" << std::fixed << f64v << ") == 0x"
        << std::hex << u64v << '\n'
        << "std::bit_cast<double>(0x" << std::hex << u64v2 << ") == "
        << std::fixed << f64v2 << '\n';
}

可能的輸出

std::bit_cast<std::uint64_t>(19880124.000000) == 0x4172f58bc0000000
std::bit_cast<double>(0x3fe9000000000000) == 0.781250

[編輯] 缺陷報告

下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。

缺陷報告 應用於 釋出時的行為 正確的行為
CWG 2482
(P1272R4)
C++20 當涉及不確定位時,是否會發生 UB 是未指定的 已指定

[編輯] 另請參閱

在給定儲存中隱式建立物件,並重用物件表示
(函式模板) [編輯]