gpt4 book ai didi

c++ - 如何在 C++11 中构建具有在编译时递增值的整数成员的结构序列

转载 作者:行者123 更新时间:2023-11-30 03:22:33 25 4
gpt4 key购买 nike

在嵌入式环境中工作时,我反复编写代码,从协议(protocol)层获取字节数组并将这些字节转换为 C++ 类表示形式。

代表 uint32_t 的示例字节数组,后跟 uint8_t,再后跟 uint16_t 可能如下所示。

std::array<uint8_t, 7> bytes(0x01, 0x02, 0x03, 0x04, 0x10, 0x20, 0x30);

其中 0x01020304 是我的 uin32_t0x10 是我的 uint8_t0x2030是我的 uint16_t

我还有一个可变参数函数 func(),我想用从有效载荷中解析出的值来调用它。

为此,我手动定义了一个中间对象:

// Declaring the Object
struct MY_TYPE
{
uint32_t val1;
uint8_t val2;
uint16_t val3;
} __attribute__((__packed__));

// Processing the Bytes
auto & object(reinterpret_cast<MY_TYPE *>(&bytes));

func(object.val1, object.val2, object.val3)

我想做的是实现一个可变类,这样我就不需要为每种类型的组合重新实现 MY_TYPE

这是我最初尝试的:

template <typename... Types>
struct GENERIC_CLASS
{
template <typename ReturnType, std::size_t ArraySize>
ReturnType getValueFromArray(std::array<uint8_t, ArraySize> const & array,
uint32_t & index);

// Note, not valid c++ since the size of the array (N) isn't
// specified. This has been omitted for simplicity.
void process(std::array<uin8_t, N> const & array)
{
auto currentIndex(u0);

// Assumes this class has a specialization
// for getValueFromArray for all of the types in Types.

// This code doesn't work because there is no sequence point
// between each call to getValueFromArray, so the
// currentIndex can be incremented in a non-deterministic way.
func(this->getValueFromArray<Types>(array, currentIndex)...);
}
};

我能够通过引入一个新类来解决这个问题:

template <typename T, std::size_t position>
struct Param
{
using type = T;
static constexpr std::size_t offset = position;
};

这样,我可以在代码中指定每个参数的偏移量,而不是在运行时维护 currentIndex,如下所示:

GENERIC_CLASS<Param<uint32_t, 0>, Param<uint8_t, 4>, Param<uint16_t, 5>>

以上内容可能容易出错,因为偏移量可能是错误的。有没有办法通过累积大小从类型的参数包生成我的 Params 序列?

或者,对于我上面提到的序列点问题,是否有一些解决方法?

最佳答案

我提出以下解决方案

#include <array>
#include <tuple>
#include <iostream>

template <typename ... Ts>
class process
{
private:

template <typename T>
static T getVal (std::uint8_t const * a)
{
T ret { *a++ };

for ( auto i = 1U ; i < sizeof(T) ; ++i )
{
ret <<= 8;
ret += *a++;
}

return ret;
}

static std::size_t postIncr (std::size_t & pos, std::size_t add)
{
std::size_t ret { pos };

pos += add;

return ret;
}

public:
template <std::size_t N>
static std::tuple<Ts...> func (std::array<std::uint8_t, N> const & a)
{
std::size_t pos { 0U };

return { getVal<Ts>(a.data()+postIncr(pos, sizeof(Ts)))... };
}
};

int main ()
{
std::array<std::uint8_t, 7U>
bytes{{0x01U, 0x02U, 0x03U, 0x04U, 0x10U, 0x20U, 0x30U}};

auto tpl
{ process<std::uint32_t, std::uint8_t, std::uint16_t>::func(bytes) };

std::cout << "- 0x" << std::hex << std::get<0>(tpl) << std::endl;
std::cout << "- 0x" << int(std::get<1>(tpl)) << std::endl;
std::cout << "- 0x" << std::get<2>(tpl) << std::endl;
}

如果您收到(正如我收到的)来自 ret <<= 8; 的恼人警告来自 getVal() (当 Tstd::uint8_t ;警告“shift count >= width of type”)你可以开发第二个 getVal对于 std::uint8_t (无循环且无移位),仅在 sizeof(T) == 1 时启用它并仅在 sizeof(T) > 1 时启用第一个.

否则你可以替换ret <<= 8;和几个 ret <<= 4; .

关于c++ - 如何在 C++11 中构建具有在编译时递增值的整数成员的结构序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51064910/

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