As shown in the code and output below, three phenomena can be observed:
- For mem_fn, which is
f1in the code, whether it is passedffor&ff, thenum_value in theffobject can be modified normally after execution. - For bind, if
ffis bound in advance, thenum_value inffobject is not modified after execution; If you use placeholder to passffor bound&ffdirectly, it can be modified as normal. - For function, if the first parameter is specified as
Foo, thenffis passed, and thenum_value in theffobject is not modified after execution.
So my problem is that all callable objects are called just like INVOKE(f, t1, t2, ..., tN). Why do the above three differences occur ?
#include <cstdio>
#include <functional>
#include <iostream>
using namespace std;
struct Foo
{
Foo(int num) : num_(num) {}
void print_add(int i) { num_ += i;}
int num_;
};
int main()
{
// cout << "check mem_fn" << endl;
Foo ff(1);
auto f1 = std::mem_fn(&Foo::print_add);
f1(ff, 1);
cout << "mem_fn pass ff, after exec, ff num : " << ff.num_ << endl;
f1(&ff, 1);
cout << "mem_fn pass &ff, after exec, ff num : " << ff.num_ << endl;
auto f2 = std::bind(&Foo::print_add, placeholders::_1, placeholders::_2);
f2(ff, 1);
cout << "bind use placeholder_1 to pass ff, after exec, ff num : " << ff.num_ << endl;
std::function<void(int)> f3 = std::bind(&Foo::print_add, ff, placeholders::_1);
f3(1);
cout << "bind pass ff, after exec, ff num : " << ff.num_ << endl;
std::function<void(int)> f4 = std::bind(&Foo::print_add, &ff, placeholders::_1);
f4(1);
cout << "bind pass &ff, after exec, ff num : " << ff.num_ << endl;
auto f5 = std::bind(f1, placeholders::_1, placeholders::_2);
f5(ff, 1);
cout << "bind_mem_fn pass ff, after exec, ff num : " << ff.num_ << endl;
auto f6 = std::bind(f1, placeholders::_1, placeholders::_2);
f6(&ff, 1);
cout << "bind_mem_fn pass &ff, after exec, ff num : " << ff.num_ << endl;
std::function<void(Foo, int)> f7 = &Foo::print_add;
f7(ff, 1);
cout << "function(Foo), pass ff, after exec, ff num : " << ff.num_ <<endl;
std::function<void(Foo*, int)> f8 = &Foo::print_add;
f8(&ff, 1);
cout << "function(Foo*), pass ff*, after exec, ff num : " << ff.num_ <<endl;
}
The output like this:
mem_fn pass ff, after exec, ff num : 2
mem_fn pass &ff, after exec, ff num : 3
bind use placeholder_1 to pass ff, after exec, ff num : 4
bind pass ff, after exec, ff num : 4
bind pass &ff, after exec, ff num : 5
bind_mem_fn pass ff, after exec, ff num : 6
bind_mem_fn pass &ff, after exec, ff num : 7
function(Foo), pass ff, after exec, ff num : 7
function(Foo*), pass ff*, after exec, ff num : 8
What you observe is the difference between making a copy of
ffand not making a copy. In all cases, the callables call the member function and the member is modified. Only sometimes you do not see the modification onffbecause the modification is on a copy offf.Here:
a copy is made. And here
as well.
The difference boils down to the difference between those two:
Calling those two looks the same just like
f1(ff,1)andf7(ff,1)looks the same, but they do something different: