没有编译器支持Constexpr Memcpy的bit_cast可能吗?
is bit_cast without compiler support for constexpr memcpy possible?
我听说std::bit_cast
将在C++20中,我对实现它必然需要特殊编译器支持的结论感到有些困惑。
公平地说,我听到的论点是实现执行memcpy
操作,并且memcpy
通常不是constexpr
,而std::bit_cast
应该是,因此制作std::bit_cast
constexpr
应该需要编译器支持符合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
成员读取不应仍然是未定义的行为,不是吗?
当然,我完全有可能在这里错过了一些非常明显的东西......我当然不能声称自己比制定这些标准的人更聪明,但如果有人能确切地告诉我我在这里调用了哪些未定义的行为,我真的很想知道。
在持续评估期间不允许做的一件事是,来自 [expr.const]/4.9:
应用于指代联合或其子对象的非活动成员的 glvalue 的左值到右值转换;
这就是您的实现所做的,因此它不是一个可行的实施策略。
此处使用易失性成员来强制编译器发出必要的代码
如果您需要编写volatile
以确保编译器不会优化您的代码,那么您的代码是不行的。编译器无法修改有效代码的可观察行为。如果你想做的(没有volatile
(是定义的行为,编译器将不允许优化你想要强制使用易失性的写入和读取。
UB 来自这样一个事实,即您只被允许读取联合的活动成员(在您的示例中in
(,但您读取非活动成员(在您的示例中out
(。
- 芬威克树(BIT).找到具有给定累积频率的最小索引,单位为 O(logN)
- 如何理解C++标准N3337中的expr.const.cast子句8
- C++Cast运算符过载
- 错误:"cast"未命名类型void setCastDescription(std::string
- 通过使用 const-cast 的非常量引用来延长临时的寿命
- "(void) cast"与功能有什么区别 "__attributes__"来沉默未使用的参数警告?
- WinAPI IcmpSendEcho on 64-bit platform
- C++:"Expected '(' for function-style cast or type construction"错误
- 将硬盘驱动器上的 BIT XXX 从 0 更改为 1
- 为什么选择 g++ 给予者:"error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]"
- Gtk+ g_signal_connect() 和 C++ lambda 会导致"invalid cast"错误
- 如何使用'bit-blast'方法以命题逻辑形式打印给定的公式?
- Shared_ptr cast vs static_cast speed
- 仅在测试中"dlopen failed: is 32-bit instead of 64-bit"
- 在 iOS 上使用 Aruco 构建 OpenCV 时"Functional-style cast from id to double is not allowed"
- 覆盖 CAST 运算符(我认为它被称为向下转换)
- 将枚举类型保存在位字段 [dcl.enum] [class.bit] 中
- C++错误,隐 <function-style-cast> 式要求使用模板化类一次调用多个构造函数的多个转换
- 如何修复<function-style-cast>错误:无法从'initializer list'转换为asdending比较<W>(模板函子)
- AES CBC 128 bit encryption -OpenSSL