I need to choice the particular method of the class at the run time. To do it I use std::bind. Below is an example demonstrating what I do:
#include<iostream>
#include<functional>
class bc {
public:
bc(int, double);
std::function<double(double)> f; //pointer to function which will be binded with f1 or f2
void setVal(double v) {val = v;} //method allowing to change val
double val; //some variable used by f1 and f2
double f1(double v) {return 2*v*val;}
double f2(double v) {return 3*v*val;}
};
bc::bc(int fid, double v) //depends on fid the f1 or f2 is chosen for binding
{
using namespace std::placeholders;
this->val = v;
if(fid == 1)
f = std::bind(&bc::f1, *this, _1);
else
f = std::bind(&bc::f2, *this, _1);
}
So depends on the value of fid given to the constructor the necessary implementation (f1 or f2) is chosen. Then in the main:
int main()
{
bc my(1, 2.0);
std::cout << my.f(1) << std::endl; //1
my.setVal(5.0);
std::cout << my.f(1) << std::endl; //2
return 0;
}
The first output from string //1 is as expected: 4 .
But the second output (//2) is also 4, while it should be 10, because the value of val should be changed to 5 by my.setVal(5.0).
I expect that something like a copy of the class was made at the stage of binding, and the change of the val by my.setVal(5.0) have no effect on this "copy".
How can I solve this problem? Or may be there is a better way to make run time choice between several implementations of some function.
CodePudding user response:
Do not dereference this before passing it to std::bind:
if(fid == 1)
f = std::bind(&bc::f1, this, _1);
else
f = std::bind(&bc::f2, this, _1);
By default std::bind stores copies of the arguments, so you ended up with a copy of bc in it, and changing the val field of the original has no effect. Alternatively, you can use std::reference_wrapper to achieve the same effect:
if(fid == 1)
f = std::bind(&bc::f1, std::ref(*this), _1);
else
f = std::bind(&bc::f2, std::ref(*this), _1);
CodePudding user response:
*this causes a copy of the current object to be bound, use this or std::ref(*this) instead.
