wyer33
wyer33

Reputation: 6340

Does std::move need to be combined with std::forward when using forwarding references?

Does std::move need to be combined with std::forward when using universal references? For example, which of the following two pieces of code is correct?

void bar(auto && x) {
    auto y(std::move(std::forward<decltype(x)>(x)));
}

or

void bar(auto && x) {
    auto y(std::move(x));
}

Basically, I want to move the memory of x into y and I don't care if it's an l-value reference or an r-value reference. Certainly, I don't want const values here.

Upvotes: 1

Views: 203

Answers (2)

Six
Six

Reputation: 31

/!\ BEWARE /!\

Using std::move for a universal reference can be a very bad idea and highly recommended to avoid :

auto name = getName(); // std::string getName();
bar(name);
// 'name' value has been moved... And its value now is unknown, empty at best.

move(forward(x)) is bad style and shouldn't be used.

You should use std::move for rvalue references and std::forward for universal references. Cf. formal definitions.

auto&& is a universal reference, therefore what you should write is :

void bar(auto&& x) {
    auto y(std::forward<decltype(x)>(x));
}

Upvotes: 0

Columbo
Columbo

Reputation: 60979

A move will suffice if you want to move regardless of the value category of the argument.
forward is superfluous in that case as move(forward(x)) is always an rvalue, no matter what forward(x) is.

If you only wanted to move depending on whether the argument to bar was an rvalue, you should use forward on its own, which propagates the value category.

Upvotes: 2

Related Questions