bit_cast将拥有除memcpy之外的其他UB(如果有的话)?

时间:2019-11-22 00:58:02

标签: c++ c++20 type-punning

我有一个类,其目的是将可能具有对齐限制的数据移入或移出未对齐数据的串行化内存缓冲区。我已设置并获取处理程序,如下所示:

#include <cstring>
template<typename T>
struct handle_type {    
    static inline T get(const void *data) {
        T value;
        memcpy(&value, data, sizeof(T));
        return value;
    }
    static inline void set(void *data, T value) {
        memcpy(data, &value, sizeof(T));
    }
};

c ++ 20发布后,我希望它会变成如下所示:

#include <bit>
template<typename T>
struct handle_type {    
    union unaligned { char bytes[sizeof(T)];  }; // EDIT: changed from struct
    static inline T get(const void *data) {
        return std::bit_cast<T>(*(const unaligned*)data);
    }
    static inline void set(void *data, T value) {
        *(unaligned *)data = std::bit_cast<unaligned>(value);
    }
};

它将起作用吗?还是我使用的是惯性类型(不对齐的结构类型)容易引起问题?

1 个答案:

答案 0 :(得分:2)

除非用户提供了指向get对象的指针,否则您的unaligned函数是UB。除非setdata对象,否则您的unaligned函数是UB。这两种情况均违反严格的别名。请记住:严格的别名后门是关于实际的char*;与恰好包含char*的对象不同。

另外,set可能是编译错误,这完全取决于unaligned的实现是否与T相同。毕竟,unaligned可能在末尾有填充。

bit_cast主要要处理对象,而不是内存的随机缓冲区。为此,您应该坚持使用memcpy


  

<已更改为使用union代替struct>

那什么都没有改变;使用union不能保证union的大小等于其最大数据成员的大小。从[class.union] / 2:

  

联合的大小足够,以包含其最大的非静态数据成员。

重点添加:“足够”,而不是“等于”。该标准允许实现使联合的大小大于其最大数据成员的能力,因为这样的大小仍将“足够”。