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.
- Change to
T foo(byte* buffer)
. This way, when passingbuffer
tofoo
, decay happens first, resulting in an r-value of typebyte*
(thinking about it as an unnamed temporary intermediate result) be passed tofoo
by value and that is okay. - 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]
.