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
.
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.
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 .
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.
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.
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?
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>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With