c++ - Can I forward an array type to a function invoked via pointer perfectly, without the argument decaying? - Stack Overflow

I have an issue that boils down to an example like this:#include <cstdlib>#include <utility&

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?

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?

Share Improve this question edited Mar 3 at 15:19 Jason R asked Mar 3 at 14:56 Jason RJason R 11.8k9 gold badges56 silver badges88 bronze badges 4
  • 2 Out of curiosity, what happens if you use a C++ array (std::array) instead of a C-style array? – Eljay Commented Mar 3 at 15:06
  • std::array (or any other C++ object type) works fine, which makes sense as the issue seems to be array-to-pointer decay. – Jason R Commented Mar 3 at 15:09
  • Another data point: (*func_ptr)(data{std::forward<T>(t)}); works for g++-14 -std=c++17. – Eljay Commented Mar 3 at 15:15
  • Even removing template part, and just call func_ptr(arr) fails :-/ Demo – Jarod42 Commented Mar 3 at 15:39
Add a comment  | 

1 Answer 1

Reset to default 3

This is a documented bug in GCC. That is to say that clang (and msvc) are correct.

Here is the "meta-bug" covering a few variations on it. Like this which applies even when there is no template.

clang is correct because zero standard conversions should be required to match the target function.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745087945a4610518.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信