First of all, I have read through this article, explaining the functionalities of std::move and std::forward. In that post, there is an example code snippet as follows which I use in my test.
std::map<std::string, std::function<void()>> commands;
template<typename ftor>
void install_command(std::string name, ftor && handler)
{
commands.insert({
std::move(name),
std::forward<ftor>(handler)
});
}
As I want to experiment on the actual usage, I have written a simple piece of code as shown below.
#include <iostream>
#include <map>
#include <functional>
using namespace std;
// code copied from above goes here
void fnA() { cout << "Function A." << endl; }
function<void()> fnB = [&]() -> void {
cout << "Function B." << endl;
}
void RunTest() {
install_command("#1", fnA);
install_command("#2", move(fnA));
install_command("#3", fnB);
//install_command("#4", move(fnB));
fnA();
fnB();
for (const auto& p : commands) {
cout << p.first.c_str() << ": " << &p.second << endl;
}
}
int main() {
RunTest();
return 0;
}
The program is compiled with -std=c++11, and the execution result is as follows.
Function A.
Function B.
#1: 0xaf8088
#2: 0xaf8018
#3: 0xaf81a8
If I uncomment the line install_command("#4", move(fnB));, there is a runtime error.
terminate called after throwing an instance of 'std::bad_function_call'
what(): bad_function_call
Function A.
I believe the ownership of the lambda function has been transferred from function<void()> fnB to commands["#4"], but why does fnA() work while fnB() does not?
fnA is a regular function not a std::function as fnB
When you do
commands.insert({
std::move(name),
std::forward<ftor>(handler)
})
You create
std::function<void()> from void(&)() for fnAstd::function<void()> from void(&)() for std::move(fnA)std::function<void()> from std::function<void()>& for fnB (so copy constructor)std::function<void()> from std::function<void()>&& for std::move(fnB) (so move constructor)Only the later modify input argument.
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