gpt4 book ai didi

c++ - 在 C++ 中获取类型的底层位的通用且可移植的方法是什么?

转载 作者:行者123 更新时间:2023-12-01 14:20:09 25 4
gpt4 key购买 nike

我想采用一个不大于指针的任意类型并获取其位表示。我尝试使用 std::bit_cast ,但这要求两种类型的大小相同。但是,由于通用性,我不知道输入类型的大小。我写了这个函数:

template<class To, class From>
To sloppy_bit_cast(From x) {
To temp{0};
std::memcpy(&temp, &x, std::min(sizeof(From), sizeof(To)));
return temp;
}
它可以在我的计算机上运行,​​但我担心 memcpy 调用会根据字节顺序表现不同。这里还有我需要担心的其他可移植性陷阱吗? std::bitset 的转换函数是否已经可移植地解决了这个问题?
编辑:具体来说,我想从最低有效位复制到最低有效位。
如果你有兴趣,这里是目前的全部代码(我还没有测试过,但我的 linter 接受了它,至少感觉是对的)。我不是要你阅读或复习它(尽管我很乐意听到反馈)。但我很高兴你们都帮我解决了这个问题,所以我想分享一下。
我在玩省略断言不仅仅是为了让我在那里得到一般的想法,但我想我可以解决这个问题来限制
#include <array>
#include <cstring>
#include <cstdint>


template<class T>
constexpr T narrow_cast(auto x) noexcept{
return static_cast<T>(x);
}

template<class To, class From>
constexpr To bit_cast(From x) noexcept {
static_assert(sizeof(To) == sizeof(From));
To temp;
std::memcpy(&temp, &x, sizeof(To));
return temp;
}

template<class T>
constexpr auto bytes_of(T x) noexcept {
return bit_cast<std::array<std::byte, sizeof x>>(x);
}

template<class T>
constexpr T to_integer(auto x) noexcept{
return static_cast<T>(x);
}

template<class UInt, class T>
constexpr auto as_UInt(T x) noexcept {
auto const bytes = bytes_of(x);
UInt acc{};
//endian agnostic
for (auto i = 0u; i < bytes.size(); ++i) {
auto const this_byte = to_integer<UInt>(bytes[i]);
acc |= (this_byte << (i * 8u));
}
return acc;
}

template<class To, class UInt>
constexpr auto from_UInt(UInt from) noexcept {
std::array<std::byte,sizeof(To)> bytes;
//endian agnostic?
for (auto i = 0u; i < bytes.size(); ++i){
bytes[i] = narrow_cast<std::byte>((from >> (i * 8u)) & 0xFFu);
}
return bit_cast<To>(bytes);
}

template<class T>
constexpr auto as_uintptr_t(T x) noexcept {
return as_UInt<uintptr_t>(x);
}

template<class To>
constexpr auto from_uintptr_t(uintptr_t x) noexcept {
return from_UInt<To>(x);
}

template<class X, class Y, int low_bit_count_ = sizeof(Y) * 8>
class uintptr_pair {
static_assert(sizeof(X) <= sizeof(uintptr_t));
static_assert(sizeof(Y) <= sizeof(uintptr_t));

public:
static constexpr auto low_bit_count = low_bit_count_;
static constexpr auto high_bit_count = sizeof(uintptr_t)*8 - low_bit_count;
constexpr uintptr_pair() = default;
constexpr uintptr_pair(X x, Y y) noexcept
: x_{as_uintptr_t(x)}, y_{as_uintptr_t(y)} {}

constexpr X x() const noexcept { return from_uintptr_t<X>(x_); }
constexpr Y y() const noexcept { return from_uintptr_t<Y>(y_); }

private:
uintptr_t x_ : high_bit_count;
uintptr_t y_ : low_bit_count;
};

constexpr auto test() {
uintptr_pair<int, int> p{3, 4};
return std::pair{p.x(),p.y()};
}

最佳答案

您可以轻松地安排拥有正确的内存量:

template<class T>
auto get_bytes(const T &t) {
std::array<std::byte,sizeof t> ret;
std::memcpy(ret.data(),&t,sizeof t);
return ret;
}
即使 T 不是普通可复制的,这也有效,尽管您无法将字节放回 T 。 ( std::bit_cast<std::array<…>> 可能会起作用,但不能真正保证类的大小是正确的。)
如果您希望结果为 整数 ,您可以选择至少多个字节之一,然后通过 |<<(产生一个值来分析独立于字节序等问题的值)或 memcpy 从如上所述填充的数组。同样,如果 T 的字节数较少,理论上不能保证行为,但在实践中肯定会起作用。

关于c++ - 在 C++ 中获取类型的底层位的通用且可移植的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62744123/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com