我想将变量打包到一个数组中,然后使用这样的接口(interface)解包
int x; float y; double z;
auto data = PackArray(x, y, z); // serializes without padding
...
int x; float y; double z;
UnpackArray(data, x, y, z); // copies data from the array to x, y, z
我试过了
template<class... T>
constexpr size_t SumOfSizeofs(const T&...)
{
return (sizeof(T) + ...);
}
// Creates array of u8 with size = sum(sizeofs)
template <class A, class ...Rest>
auto PackArray(A& a, Rest&... rest)
{
return std::array<u8, SumOfSizeofs(a, rest...)>; // doesn't work
}
template <class Array, class...Rest>
auto UnpackArray(Array& array, Rest&... rest)
{
// iterates through sizeof each element, copying to its new buffer from the array
}
如果有 std::packed_tuple
就好了... :(
我不擅长模板语法,有帮助吗?
最佳答案
这是我的做法:
#include <array>
#include <cstddef>
#include <cstdio>
#include <cstring>
#include <memory>
#include <type_traits>
template <class... T>
[[nodiscard]] auto PackArray(T&&... args) {
static_assert(
(std::is_trivially_copyable_v<std::remove_reference_t<T>> && ...),
"Packing requires trivial-copying");
std::array<std::byte, (sizeof(T) + ... + 0)> data;
std::size_t offet = 0;
(std::memcpy(data.data() + (offet += sizeof(args)) - sizeof(args),
std::addressof(args), sizeof(args)), ...);
return data;
}
template <std::size_t sz, class... T>
auto UnpackArray(std::array<std::byte, sz> const& data, T&... args) {
static_assert(sz == (sizeof(T) + ... + 0), "Mismatch");
static_assert(
(std::is_trivially_copyable_v<std::remove_reference_t<T>> && ...),
"UnPacking requires trivial-copying");
std::size_t offet = 0;
(std::memcpy(std::addressof(args),
data.data() + (offet += sizeof(args)) - sizeof(args),
sizeof(args)), ...);
}
int main() {
int x = 42;
float y = 3.14f;
double z = 2.72;
auto data = PackArray(x, y, z); // serializes without padding
int x1;
float y1;
double z1;
UnpackArray(data, x1, y1, z1);
std::printf("%d, %.2f, %.2f", x1, y1, z1);
}
注意 std::addressof
的使用以避免对象重载 operator&
的问题。
关于C++ 可变参数模板打包到 std::array 并解包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66483145/