std::bit_cast

来自cppreference.com
< cpp‎ | numeric
在标头 <bit> 定义
template< class To, class From >
constexpr To bit_cast( const From& from ) noexcept;
(C++20 起)

通过转译 from 的对象表示获得 To 类型值。返回的 To 对象值表示中的每位都等于 from 的对象表示中的对应位。返回的 To 对象中的填充位的值未指定。

若无 To 类型值对应产生的值表示,则行为未定义。若有多个这种值,则产生哪个值是未指定的。

结果的值表示中的一个位为不确定,若它

  • 不对应 From 的值表示中的位(即它对应填充位),或
  • 对应一个不在其生存期内的对象的位,或
  • 拥有不确定值

对于每个结果的值表示中的不确定位,含该位的最小对象拥有不确定值;若该对象不拥有 unsigned charstd::byte 类型则行为未定义。其他情况下结果不含不确定值。

此重载只有在 sizeof(To) == sizeof(From)ToFrom 两者都是可平凡复制 (TriviallyCopyable) 类型时才会参与重载决议。

此函数模板为 constexpr ,若且唯若 ToFromToFrom 的所有子对象的类型都:

  • 不是联合体类型;
  • 不是指针类型;
  • 不是指向成员指针类型;
  • 不是 volatile 限定类型;且
  • 无引用类型的非静态数据成员。

参数

from - 返回值的位数据源

返回值

位值如上的 To 类型对象。

可能的实现

std::bit_cast 前,如果忽略 constexpr ,需要翻译对象表示为另一类型的对象表示时,可以使用 std::memcpy

template <class To, class From>
typename std::enable_if_t<
    sizeof(To) == sizeof(From) &&
    std::is_trivially_copyable_v<From> &&
    std::is_trivially_copyable_v<To>,
    To>
// constexpr 支持需要编译器魔法
bit_cast(const From& src) noexcept
{
    // 此实现要求 To 可平凡默认构造
    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;
}

而实现 constexpr 可以尝试使用gcc内建函数:

template <class To, class From>
typename std::enable_if_t<
    sizeof(To) == sizeof(From) &&
    std::is_trivially_copyable_v<From> &&
    std::is_trivially_copyable_v<To>,
    To>
constexpr bit_cast(const From& from) noexcept
{
    return __builtin_bit_cast(_To, __from);
}


注解

大多数情况下不应该用指针或引用类型间的 reinterpret_cast (或等价的显式转型)转译对象表示,因为类型别名使用规则

功能特性测试 标准 备注
__cpp_lib_bit_cast 201806L (C++20) std::bit_cast


示例

#include <cstdint>
#include <bit>
#include <iostream>
 
constexpr double f64v = 19880124.0;
constexpr auto u64v = std::bit_cast<std::uint64_t>(f64v);
 
constexpr std::uint64_t u64v2 = 0x3fe9000000000000ull;
constexpr auto f64v2 = std::bit_cast<double>(u64v2);
 
int main()
{
    std::cout
        << std::fixed <<f64v << "f64.to_bits() == 0x"
        << std::hex << u64v << "u64\n";
 
    std::cout
        << "f64::from_bits(0x" << std::hex << u64v2 << "u64) == "
        << std::fixed << f64v2 << "f64\n";
}

可能的输出:

19880124.000000f64.to_bits() == 0x4172f58bc0000000u64
f64::from_bits(0x3fe9000000000000u64) == 0.781250f64

缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 出版时的行为 正确行为
CWG 2482 C++20 在涉及不确定位时未指定 UB 是否会出现 已指定