Initialiser list passed as function parameter for array

后端 未结 5 1363
醉梦人生
醉梦人生 2020-12-19 07:49

How do I make this work:

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

foo({0x01, 0x02, 0x03});

It gives me an error:

error: cannot conver         


        
相关标签:
5条回答
  • 2020-12-19 08:08

    This:

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

    is a function that takes a uint8_t*, not an array - arrays are decayed to pointers when used as function arguments. The issue is that an initializer list (like {0x01, 0x02, 0x03}) cannot be converted to a uint8_t*.

    If what you want is to pass an arbitrary number of uint8_ts to foo, the simple solution is to use the new std::initializer_list

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

    Or you could take a variadic pack and construct an array from it internally:

    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...};
        // ...
    }
    

    That has slightly different usage:

    foo({0x01, 0x02, 0x03}); // error
    foo(0x01, 0x02, 0x03; // OK - a has 3 elems in it
    
    0 讨论(0)
  • 2020-12-19 08:19

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

    0 讨论(0)
  • 2020-12-19 08:23

    The answers so far haven't addressed the main problem with the question: In the signature

    void foo(uint8_t a[])
    

    a is not an array, but a pointer to a uint8_t. This is despite the fact that the declaration of a makes it look like an array. This is even pointed out by the error message:

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

    So, in the same way you are not allowed to do this:

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

    You can't call foo({0x01, 0x02, 0x03}); With the signature above.

    I suggest you take some time to read up on C-style arrays and how they are not first-class citizens in C++.

    From the answer you posted to your own question, it seems that you are looking for a function that works for fixed-size arrays. But don't pass it by value! I recommend using the following declaration:

    void foo(std::array<uint8_t, 3> const &a);
    
    0 讨论(0)
  • 2020-12-19 08:33

    You cannot. Just construct

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

    and call foo(a).

    Or just use std::array, that is probably better.

    0 讨论(0)
  • 2020-12-19 08:34

    This worked for me, I had to change the function signature but it's actually better in my case as it statically checks the array length:

    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.
    
    0 讨论(0)
提交回复
热议问题