The distinction between std::move
and std::forward
is well known, we use the latter to preserve the value category of a forwarded object and the former to cast to rvalue reference in order to enable move semantics.
In effective modern C++, a guideline exists that states
use
std::move
on rvalue references,std::forward
on universal references.
Yet in the following scenario (and scenarios where we don't want to change value category),
template <class T>
void f(vector<T>&& a)
{
some_func(std::move(a));
}
where a
is not a forwarding reference but a simple rvalue reference, wouldn't it be exactly the same to do the following?
template <class T>
void f(vector<T>&& a)
{
some_func(std::forward<decltype(a)>(a));
}
Since this can be easily encapsulated in a macro like this,
#define FWD(arg) std::forward<decltype(arg)>(arg)
isn't it convenient to always use this macro definition like so?
void f(vector<T>&& a)
{
some_func(FWD(a));
}
Aren't the two ways of writing this exactly equivalent?
Eh. Debatable. In your particular example it is equivalent. But I wouldn't make it a habit. One reason is because you want a semantic distinction between forwarding and moving. Another reason is because to have a consistent API you'd have to have MOV
in addition to FWD
, and that really looks bad and doesn't do anything. More importantly, though, is that your code can fail unexpectedly.
Consider the following code:
#include <iostream>
using namespace std;
#define FWD(arg) std::forward<decltype(arg)>(arg)
struct S {
S() { cout << "S()\n"; }
S(const S&) { cout << "S(const S&)\n"; }
S(S&&) { cout << "S(S&&)\n"; }
};
void some_func(S) {}
void f(S&& s)
{
some_func(FWD(s));
}
int main()
{
f(S{});
}
This prints out
S()
S(S&&)
However, if I just change the FWD
line to have another (seemingly optional) pair of parentheses, like this:
void f(S&& s)
{
some_func(FWD((s)));
}
Now we get
S()
S(const S&)
And this is because now we're using decltype
on an expression, which evaluates to an lvalue reference.
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