我需要初始化一个uint8_t数组, 大部分是常量(固定标识符),一些元素编码下一节的长度,一些元素是可变的。
uint8_t data[] = {
0x01, 0x05, 0x06, SomeVariable, 0x13,0x09, OtherVariable
};
我想用命名组件来组合它,像这样
uint8_t data[] = MyData(DataHeader(), DataValue(SomeVariable), OtherValue(OtherVariable))
MyData 将连接任意数量的参数并生成
{
0x01, length of all parameters,
data from first parameter...,
data from second parameter...,
...
}
DataValue 将产生
{0x06, SomeVariable}
,
OtherValue 将产生 {0x13, 0x09, OtherVariable}
,
等等
如何在 C++ 中做到这一点,无需动态分配(结果数组的总大小在编译时已知)?
我尝试将
template
与 constexpr
和参数包一起使用,但失败了,因为数组中的值不是 constexpr。然而数组的大小是 constexpr,所以我希望它可以完成。
虽然我不清楚您所描述的内容会给您带来什么好处,但有一些问题需要解决。让我们从语法开始:
uint8_t data[] = MyData()
只有当 MyData() 返回一个初始值设定项列表时,这才有可能。然而这是不可能的,因为初始化列表不会延长底层数组的生命周期(reference)。如果您
return std::initializer_list<uint8_t>{1,2,3}
那么它将在 return 语句完成之前被销毁。
但是,您可以让 MyData 分配内存并返回地址:
uint8_t* MyData() { uint8_t data = new uint8_t[16]; }
uint8_t* data = MyData();
但是你需要销毁数据。另一种方法是将指针传递给 MyData:
void MyData(uint8_t* ptr) { ptr[0] = 0x13; }
uint8_t data[16];
MyData(data);
现在,您可以编写
MyData
来获取可变参数:
void MyData(uint8_t* ptr, std::initializer_list<uint8_t> list){
size_t i = 0;
for (auto element : list)
ptr[i++] = element;
}
uint8_t data[16];
MyData(data, {0x01, 0x02});
如上所述,您不能让函数返回 initalizer_lists。你可以尝试一下,但最终可能不会让它变得更漂亮。
你描述它的方式,听起来你可以使用预处理器来做你想做的事。编写 macros 来填充初始化列表。