Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perfect forwarding

If we have the following:

template <class T>
struct B{
  T data;
}

struct A{
  int data_array[100];
}

int main()
{
  A x;
  const A x_const;

  auto y1 = f(A());
  auto y2 = f(x);
  auto y3 = f(x_const);
  auto y4 = f(std::move(x));
}

I want to know an f (preferably function, but macro is okay also) such that:

decltype(y1) == B<A>
decltype(y2) == B<A&>
decltype(y3) == B<const A&>
decltype(y4) == B<A&&>

That is, f perfectly forwards x into an object of B.

like image 561
Clinton Avatar asked Jun 09 '11 01:06

Clinton


People also ask

What is perfect forwarding?

Perfect forwarding allows a template function that accepts a set of arguments to forward these arguments to another function whilst retaining the lvalue or rvalue nature of the original function arguments.

Why do STDS forward?

It is typically used with template functions where reference collapsing may have taken place (involving universal/forwarding references). Consider the code sample below. Removing the std::forward would print out requires lvalue and adding the std::forward prints out requires rvalue .

What is forwarding reference in C++?

When t is a forwarding reference (a function argument that is declared as an rvalue reference to a cv-unqualified function template parameter), this overload forwards the argument to another function with the value category it had when passed to the calling function.

What is reference collapsing?

Reference collapsing is the mechanism that leads to universal references (which are really just rvalue references in situations where reference-collapsing takes place) sometimes resolving to lvalue references and sometimes to rvalue references.


2 Answers

This is impossible. For y1 and y4, then they both take rvalues of type A, but you want them to return different types. How should f know what to return?

like image 159
Puppy Avatar answered Oct 04 '22 21:10

Puppy


template <typename T>
auto f(T&& t) -> B<decltype(std::forward<T>(t))>
{
    return B<decltype(std::forward<T>(t))>{std::forward<T>(t)};
}

This does almost what you want. The only difference is for the first one the type is B<A&&> rather than B<A>.

like image 38
HighCommander4 Avatar answered Oct 04 '22 21:10

HighCommander4