Home > Net >  c Type error for fixed-size array being passed to template requesting array pointer
c Type error for fixed-size array being passed to template requesting array pointer

Time:10-13

I have a template function like the following:

template<typename T>    
T foo(byte* &buffer){
   ...
}

When I try to access it with a fixed-size array I get an error:

byte buffer[100] = {};
foo<int>(buffer);

However, when I create a new variable from buffer and pass that, no error:

byte buffer[100] = {};
auto b = buffer;
foo<int>(b);

What is the type of buffer? Is it not a byte*? Is there a way to cast it to a byte*? This only happens with a template function, otherwise it works as expected.

CodePudding user response:

The error in the first case is because the array buffer does not decay because you have passed it be reference. That is you cannot bind a reference to a pointer to byte to an array of byte.

While in the second case b is a pointer which you can pass by reference.

Solution 1

One way to solve this is by removing the reference from the function parameter i.e., by the argument by value. So passing by value looks like:

template<typename T>    
T foo(byte* buffer){//note pass by value
   ...
}

Note in solution 1 you can modify the array from inside the function through the pointer. One disadvantage of solution 1 is that here you can also pointer other pointers(like pointer to int) so you have to take care by yourself that you don't try to access anything that is out of bound of the array. Other alternative would be to just pass the array by reference as you originally intended as shown in Solution 2.

Solution 2 Pass the array by reference

template<typename T,  std::size_t N>
T foo(byte (&buffer)[N])//this time you're passing the actual array by reference and not the pointer to its first element
{
}

Now in solution 2 you have passed the array by reference and you can modify it directly inside the function template. Now foo<int>(buffer); will work.

CodePudding user response:

The issue has nothing to do with templates. Change foo to a non-template void foo(byte* &buffer) and you will see the same error.

buffer as declared in the function is of type non-const reference to a pointer to byte. In your second write-up, buffer is of type byte[100] with an l-value category. When assigned to b, decay happens and b is of type byte* with an l-value category. So b can be passed to foo without error. Non-const reference can be bound to a non-const l-value. Your first write-up does not work this way. Two simple fixes.

  1. Change to T foo(byte* buffer). This way, when passing buffer to foo, decay happens first, resulting in an r-value of type byte* (thinking about it as an unnamed temporary intermediate result) be passed to foo by value and that is okay.
  2. Change to T foo(byte* const buffer). Again, decay happens first, and const reference can be bound to an r-value, whereas non-const reference cannot.

If you prefer, may also declare buffer in foo to be of type non-const reference to byte[100].

  • Related