Reputation: 689
Update: Somehow related to how-is-stdfunction-implemented
The program inserts different function pointers (a multiplication from a struct, a divide as a function, and an add as lambda) into a vector and then calls the elements with the same arguments. Problems arise only from the struct.
It works well with std::function but I can not make it compile when using function pointers. Does anyone have a clue how to repair the program; or better, how does std::function works? If I use a static member function instead, the program becomes trivial (not included below).
#include <iostream>
#include <string>
#include <vector>
#include <functional>
struct mult {
double operator()(double a, double b) { return a * b; }
double fun(double a, double b) { return a * b; }
};
double add(double a, double b) {
return a + b;
}
using namespace std;
int main(){
using fnc = function<double(double, double)>;
vector<fnc> functions;
functions.push_back(mult{});
functions.push_back([](double a, double b) {return a / b; });
functions.push_back(add);
double a = 3, b = 4;
cout << "a=" << a << ", b=" << b << endl;
for (int i = 0; i < 3; ++i)
cout << functions[i](a, b) << endl;
cout << endl;
typedef double (*fp)(double, double);
fp funPtr;
vector<fp> functions1;
//functions1.push_back(mult{}); error
typedef double (mult::*mfp)(double, double);
mfp f = &mult::fun;
mult * obj = new mult;
cout << (obj->*f)(3, 4) << endl;// OK!
//functions1.push_back(mfp); ERROR!
//functions1.push_back(obj->*f); ERROR!
//functions1.push_back(&mult::fun); ERROR!
functions1.push_back([](double a, double b) {return a / b; });
functions1.push_back(add);
for (int i = 0; i < 2; ++i)
cout << functions1[i](a, b) << endl;
std::cout << "\npres enter to exit...";
int wait_key = getchar();
return 0;
}
Upvotes: 1
Views: 131
Reputation: 11261
Member functions have a hidden first parameter, which is the pointer to the object it is called on. So
double mult::operator()(double a, double b) { return a * b; }
is in fact (somewhat) equal to
double operator()(mult* this, double a, double b) {
return a * b;
}
So that's why you cannot add a mfp
type object to a vector of type fp
.
edit: what will work is
struct mult {
static double fun(double a, double b) { return a * b; }
};
fp f = &mult::fun;
functions1.push_back(f);
As by making a member function static
, it's no longer tied to an object.
and
functions1.push_back(mfp);
is probably a typo anyway, since mfp
was the typedef, and not the function object f
...
edit 2: There is also the option to use std::bind
to bind the first hidden parameter to a specific object.
E.g. using your original (non-static) member function:
mult obj;
fnc temp = std::bind(&mult::fun, &obj, std::placeholders::_1, std::placeholders::_2);
functions.push_back(temp);
Upvotes: 2