初始化程序列表作为数组的函数参数传递

Initialiser list passed as function parameter for array

本文关键字:函数 参数传递 数组 程序 列表 初始化      更新时间:2023-10-16

如何实现这一点:

void foo(uint8_t a[]) { ... }
foo({0x01, 0x02, 0x03});

它给了我一个错误:

error: cannot convert '<brace-enclosed initializer list>' to 'uint8_t* {aka unsigned char*}' for argument '1'
                                                     ^

这对我来说很有效,我不得不更改函数签名,但实际上在我的情况下更好,因为它静态地检查数组长度:

void foo(std::array<uint8_t, 3> a) { /* use a.data() instead of a */ }
foo({0x01, 0x02, 0x03}); // OK
foo({0x01, 0x02}); // Works, at least on GCC 4.9.1. The third value is set to zero.
foo({0x01, 0x02, 0x03, 0x04}); // Compilation error.

到目前为止的答案还没有解决这个问题的主要问题:在签名中

void foo(uint8_t a[])

a不是一个数组,而是指向uint8_t的指针。尽管a的声明使它看起来像一个数组。错误消息甚至指出了这一点:

cannot convert '<brace-enclosed initializer list>' to 'uint8_t* {aka unsigned char*}'

所以,以同样的方式,你不允许这样做:

uint8_t *a = {0x01, 0x02, 0x03}; // Eek! Error

你不能用上面的签名打电话给foo({0x01, 0x02, 0x03});

我建议您花一些时间来阅读C风格数组,以及它们在C++中如何不是一流的公民。

从你发布的答案到你自己的问题,似乎你正在寻找一个适用于固定大小数组的函数。但不要按价值传递!我建议使用以下声明:

void foo(std::array<uint8_t, 3> const &a);

您不能。只需构建

uint8_t a[] = {0x01, 0x02, 0x03};

并调用CCD_ 5。

或者只使用std::array,这可能更好。

这:

void foo(uint8_t a[]) { ... }

是一个采用uint8_t*的函数,而不是数组——当用作函数参数时,数组会衰减为指针。问题是初始化器列表(如{0x01, 0x02, 0x03}(无法转换为uint8_t*

如果您想要将任意数量的uint8_ts传递给foo,那么简单的解决方案是使用新的std::initializer_list

void foo(std::initializer_list<uint8_t> a) { ... }
foo({0x01, 0x02, 0x03, 0x04, 0x05}); // OK - a has 5 elems in it

或者你可以采用一个可变包,并在内部构建一个数组:

template <typename... Args,
          typename = std::enable_if_t<
              all_true<std::is_convertible<Args, uint8_t>::value...>
              >>
void foo(Args... elems) {
    uint8_t a[] = {elems...};
    // ...
}

其用法略有不同:

foo({0x01, 0x02, 0x03}); // error
foo(0x01, 0x02, 0x03; // OK - a has 3 elems in it

foo(std::array<uint8_t, 3>{0x01, 0x02, 0x03}.data());