Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is putting std::move inside a lambda really necessary here?

Tags:

c++

c++11

Do I really have to encapsulate the std::move call in a lambda?

std::list<std::wstring>     srcData = GetData(); // implementation not important
std::vector<std::wstring>   dstData;
dstData.reserve(srcData.size());
std::transform(std::begin(srcData), std::end(srcData), std::back_inserter(dstData), 
    [](std::wstring& guid) -> std::wstring { return std::move(guid); });
srcData.clear();

I am still new to lambdas and rvalue references, so initially I tried:

std::transform(std::begin(srcData), std::end(srcData), 
    std::back_inserter(dstData), &std::move<std::wstring>);

which doesn't work.

Do I have to put the move inside a lambda, or am I missing something obvious?

like image 792
utnapistim Avatar asked Dec 15 '11 12:12

utnapistim


People also ask

When should you not use std move?

However, std::move must be used judiciously; using it blithely may lead to performance degradation, or simply be redundant, affecting readability of the code. Fortunately, the compiler can sometimes help with finding such wrong uses of std::move.

How to initialize a closure object from a lambda function?

You have a lambda capture _theirStuff { std::move (theirStuff) }. This basically declares a member of the closure type, which will be initialized when the closure object is created as if it were in the lambda body.

Is it possible to call a Lambda twice?

And you would be moving _theirStuff into myStuff when the lambda is called. Note that, as a consequence, your lambda then cannot really be called twice. I mean, it can, but it will only really work once since _theirStuff will be empty after the first time the lambda is called…


1 Answers

An alternative is to use move iterators:

std::vector<std::wstring> dstData(std::make_move_iterator(srcData.begin()),
                                  std::make_move_iterator(srcData.end()));

Or use the move algorithm:

std::move(srcData.begin(), srcData.end(), std::back_inserter(dstData));

Since it was asked, here's how you could force the original proposal to work:

int main()
{
    std::transform(std::begin(srcData),
      std::end(srcData),
      std::back_inserter(dstData),
      static_cast<std::wstring&&(*)(std::wstring&)>(&std::move<std::wstring&>));
}
like image 125
Kerrek SB Avatar answered Oct 05 '22 03:10

Kerrek SB