I have an issue that boils down to an example like this:
#include <cstdlib>
#include <utility>
// class that is constructible from a `float` array type
struct data
{
template <size_t N>
data(float (&arr)[N]) { }
};
// function that takes an instance of `data`
void direct(data) { }
// pointer to the above function
void (*func_ptr)(data) = &direct;
// forward the argument to the function directly
template <typename T>
void call_direct(T && t)
{
return direct(std::forward<T>(t));
}
// forward the argument to the function invoked via pointer
template <typename T>
void call_via_ptr(T && t)
{
return (*func_ptr)(std::forward<T>(t));
}
int main()
{
float arr[4];
call_direct(arr);
call_via_ptr(arr);
}
That is, I have a function direct() that takes an argument of type data. data is constructible from a fixed-length C style array. I have another pair of functions, call_direct() and call_via_ptr(), which forward their single template argument to the function, either invoking it directly or via a function pointer.
The call_direct() approach works fine. However, the call_via_ptr() fails to compile on gcc versions through 14.2, yielding an error like:
<source>: In instantiation of 'void call_via_ptr(T&&) [with T = float (&)[4]]':
<source>:35:17: required from here
35 | call_via_ptr(arr);
| ~~~~~~~~~~~~^~~~~
<source>:27:39: error: could not convert '(float*)std::forward<float (&)[4]>((* & t))' from 'float*' to 'data'
27 | return (*func_ptr)(std::forward<T>(t));
| ~~~~~~~~~~~~~~~^~~
| |
| float*
However, it does compile fine on all clang versions that I have tried.
It looks like when calling the function via a function pointer, the array argument is decaying to a float *, which is not convertible to data, hence the error. However, it isn't clear to me why the pointer decay would work differently between the two cases.
Is there a tweak I can make here to allow this to build on gcc? Which compiler is correct here?
std::array) instead of a C-style array?std::array(or any other C++ object type) works fine, which makes sense as the issue seems to be array-to-pointer decay.(*func_ptr)(data{std::forward<T>(t)});works forg++-14 -std=c++17.func_ptr(arr)fails :-/ Demo