5

In C++20, is the following function not ill-formed:

void f(auto&&... args) { /*...*/ }

and, if not ill-formed, is there a way to forward arguments in the body (without modifying the signature) in exactly the same fashion as the following function:

template<typename... Args>
void f(Args&&... args) {
    g(std::forward<Args>(args)...);
}

If so, what should replace the use of Args as the template argument to std::forward?

Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319
  • I kinda feel like this is already answered here https://stackoverflow.com/questions/24535430/how-to-perfectly-forward-auto-in-a-generic-lambda – StoryTeller - Unslander Monica Jan 28 '21 at 07:37
  • @StoryTeller-UnslanderMonica This being variadic makes it sufficiently different I think. The correct syntax is arguably non-obvious. – cigien Jan 28 '21 at 07:40
  • @cigien - That's minutia... and a maybe grasping at straws. The grammatical difference that a pack incurs compared to a single argument is a couple of additional ellipsis. – StoryTeller - Unslander Monica Jan 28 '21 at 07:42
  • Yeah, I'm fine either way with it being a duplicate. I suspected `decltype` was the right answer, but it wasn't clear to me that it handled all the reference-collapsing / forwarding reference stuff correctly. – Andrew Tomazos Jan 28 '21 at 07:42
  • @StoryTeller-UnslanderMonica Sure, but the grammatical difference is not what a lot of future visitors would care about. and the spelling could reasonably be ``. Compilers don't say much more than "parse error here". I'm on the fence about the dupe from that pov. – cigien Jan 28 '21 at 07:44
  • @cigien - *"could reasonably be"*, except it's not. And also not the focus. The issue here is lack of an explicit template parameter to feed into `forward`, and that is exactly the same issue the other question addresses. – StoryTeller - Unslander Monica Jan 28 '21 at 07:50
  • @StoryTeller-UnslanderMonica Ok, I see that point. It's not really the focus of the question. I still think it's reasonable for someone to expect the syntax to be `decltype(args...)` or something like that, but I'm fine with the closure. – cigien Jan 28 '21 at 07:54

1 Answers1

3

You can do it with the help of decltype.

void f(auto&&... args) {
    g(std::forward<decltype(args)>(args)...);
}

When being passed lvalues, decltype(args) yields type T&, std::forward would forward them as lvalues. When being passed rvalues, decltype(args) yields type T&&, std::forward would forward them as rvalues. Note that it's a little different with the template version, in which T is specified as template argument for std::forward; the effect (i.e. forwarding as rvalues) is the same for both cases.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405