boost 多精度类型的内存布局是实现细节。所以无论如何你都不能假设太多(它们不应该是按位可序列化的)。
只需阅读文档的随机部分:
最小比特数
在诉诸动态内存分配之前确定要直接存储在对象中的位数。当为零时,该字段根据可以与动态存储标头联合存储的位数自动确定:设置较大的值可能会提高性能,因为在需要内存分配之前将在内部存储较大的整数值。
目前尚不清楚您是否有机会在内存布局中实现某种程度的“正常 int 行为”。唯一的例外是 MinBits==MaxBits。
确实,我们可以静态断言带有此类后端配置的 cpp_int 的大小与相应的字节大小匹配。
事实证明,在后端基类中甚至还有一个有希望的标签来表示“琐碎”(这确实很有希望):trivial_tag,所以让我们使用它:
Live On Coliru
#include <boost/multiprecision/cpp_int.hpp>
namespace mp = boost::multiprecision;
template <int bits> using simple_be =
mp::cpp_int_backend<bits, bits, mp::unsigned_magnitude>;
template <int bits> using my_int =
mp::number<simple_be<bits>, mp::et_off>;
using my_int8_t = my_int<8>;
using my_int16_t = my_int<16>;
using my_int32_t = my_int<32>;
using my_int64_t = my_int<64>;
using my_int128_t = my_int<128>;
using my_int192_t = my_int<192>;
using my_int256_t = my_int<256>;
template <typename Num>
constexpr bool is_trivial_v = Num::backend_type::trivial_tag::value;
int main() {
static_assert(sizeof(my_int8_t) == 1);
static_assert(sizeof(my_int16_t) == 2);
static_assert(sizeof(my_int32_t) == 4);
static_assert(sizeof(my_int64_t) == 8);
static_assert(sizeof(my_int128_t) == 16);
static_assert(is_trivial_v<my_int8_t>);
static_assert(is_trivial_v<my_int16_t>);
static_assert(is_trivial_v<my_int32_t>);
static_assert(is_trivial_v<my_int64_t>);
static_assert(is_trivial_v<my_int128_t>);
// however it doesn't scale
static_assert(sizeof(my_int192_t) != 24);
static_assert(sizeof(my_int256_t) != 32);
static_assert(not is_trivial_v<my_int192_t>);
static_assert(not is_trivial_v<my_int256_t>);
}
结论:您可以拥有微不足道的 int 表示直到某一点,之后您将获得基于分配器的动态肢体实现无论如何。
鉴于此,您可能能够利用 hacksIF 实现您想要做的事情,您的后端配置支持微不足道。遗憾的是,我认为它需要您手动重载 endian_reverse 以实现 128 位大小写,因为 GCC builtins 没有 __builtin_bswap128,Boost Endian 也没有定义。
我建议在这里处理How to make GCC generate bswap instruction for big endian store without builtins?的信息
最终演示(未完成)
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/endian/buffers.hpp>
namespace mp = boost::multiprecision;
namespace be = boost::endian;
template <int bits> void check() {
using T = mp::number<mp::cpp_int_backend<bits, bits, mp::unsigned_magnitude>, mp::et_off>;
static_assert(sizeof(T) == bits/8);
static_assert(T::backend_type::trivial_tag::value);
be::endian_buffer<be::order::big, T, bits, be::align::no> buf;
buf = T("0x0102030405060708090a0b0c0d0e0f00");
std::cout << std::hex << buf.value() << "\n";
}
int main() {
check<128>();
}
(将be::order::big 更改为be::order::native 显然可以编译。完成它的另一种方法是为您的int 类型为endian_reverse 设置一个ADL 可访问重载。)