Given the following working code (main.cpp):
#include <functional>
#include <iostream>
struct worker
{
std::function<bool(std::string)> m_callback;
void do_work(std::function<bool(std::string)> callback) // <--- this line
{
m_callback = std::bind(callback, std::placeholders::_1);
callback("hello world!\n");
}
};
// pretty boring class - a cut down of my actual class
struct helper
{
worker the_worker;
bool work_callback(std::string str)
{
std::cout << str << std::endl;
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work( [&](std::string data){ return the_helper.work_callback(data); });
}
Compiled with: -std=c++11 -O2 -Wall -Wextra -pedantic-errors -O2 main.cpp
I have comment the line in question ( <-- this line
- around line 7), where I think it would be more efficient to use: void do_work(std::function<bool(std::string)>&& callback)
ie using the &&
move semantic.
I have never really used this, mostly because I still don't quite understand it.
My understanding is this:
void do_work(std::function<bool(std::string)> callback)
- will take a copy of the lambda that I pass in (which is an rvalue I think).
void do_work(std::function<bool(std::string)> callback)
- will move the lambda that I pass in because it is an rvalue.
My crude idea of an rvalue is any temporary variable.
Questions:
What I am not 100% clear about is, is what I wrote correct? and therefore is it safe to use &&
. Both seem to work.
Does this &&
method also work if instead of passing a lambda like this:
the_helper.the_worker.do_work( [&](std::string data){ return the_helper.work_callback(data); });
we pass in std::bind(...):
the_worker.do_work(std::bind(&helper::work_callback, the_helper, std::placeholders::_1));
If the parameter is defined as an rvalue-reference, you must pass a temporary or cast an lvalue to an rvalue, like with std::move()
.
And the semantics of rvalue-references are that the caller should expect the passed argument to be plundered, rendering it valid but arbitrary, meaning mostly useless.
But the function receiving an rvalue-reference, despite having license to plunder , does not have any obligation to plunder . And if it doesn't explicitly do so, for example by passing that license on, then it doesn't come to pass, and nothing special happens.
Your code is such a case.
While I would ban std::bind
from my vocabulary, using it or not doesn't actually make any significant difference.
In this case regardless of whether you pass by value or by rval ref a temporary std::function will have to be created, that's because a lambda is not really a std::function. In any case, you should move the std::function before assigning, to avoid making an unnecessary copy.
I'd recommend passing by value in this case, as this is a bit more flexible, and if you are passing lambdas, then it does not cause any harm, as the std::function will usually be constructed in place (so the temporary will not be moved into the function; this move can, and usually will, be elided).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.