【发布时间】:2020-02-17 00:47:23
【问题描述】:
我听说std::bit_cast 将在 C++20 中使用,我对实现它必然需要特殊编译器支持的结论感到有些困惑。
公平地说,我听到的论点是实现执行memcpy 操作,而memcpy 通常不是constexpr,而std::bit_cast 应该是,所以使std::bit_cast @987654328 @ 据说需要编译器支持 constexpr 兼容的 memcpy 操作。
不过,我想知道,是否可以在根本不实际调用 memcpy 的情况下实现兼容的 bit_cast(即定义的行为,其程度与使用 memcpy 的定义行为相同)。
考虑以下代码:
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 成员读取不应该仍然是未定义的行为,不是吗?
当然,我完全有可能在这里遗漏了一些非常明显的东西......我当然不能声称自己比制定这些标准的人更聪明,但是如果有人能准确地告诉我我有哪些未定义的行为我在这里调用,我真的很想知道它。
【问题讨论】:
标签: c++ undefined-behavior constexpr c++20 type-punning