std::transform with virtual call operator throws "global functions do not have 'this' pointers"

StackOverflow https://stackoverflow.com/questions/18315582

  •  25-06-2022
  •  | 
  •  

Question

PayOff is an abstract base class and CallPayOff and PutPayOff derive from it. The call operator is defined as a pure virtual function in base class and CallPayOff and PutPayoff provide their own implementations.

vector<PayOff*> v;
v.push_back(new CallPayOff(20));
v.push_back(new PutPayOff(20));
vector<double> payVals;
payVals.reserve(v.size());
transform(v.begin(), v.end(), back_inserter(payVals),  bind2nd(mem_fun(&PayOff::operator()),this));

Call operator is defined as:

class PayOff
{
public:
    virtual double operator()(double spot)const = 0;
    virtual ~PayOff(){}
};

Can anyone please take a look? Boost/C++11 is not an option.

Was it helpful?

Solution 2

You don't say what you expect the transform to do; presumably it's to invoke each PayOff object on some value. In that case the functor should be:

bind2nd(mem_fun(&PayOff::operator()),some_value)

or, for those not stuck in the past,

[=](PayOff* p){(*p)(some_value;}}

or

bind(&PayOff::operator(), _1, some_value);

You are instead trying to bind to this which, in a global function, doesn't exist. In a member function, it would exist, but wouldn't make sense as an argument to a functor that expects a double.

OTHER TIPS

transform(v.begin(), v.end(), payVals.begin(),  
          bind2nd(mem_fun(&PayOff::operator()),this));

The names in the call to transform must be looked up and resolved at the place where the call takes place. Which according to your comment is main. Inside main, you cannot use this.

If you have a C++11 compiler you can opt to either use a lambda or std::bind:

std::transform(std::begin(v), std::end(v),
               std::begin(payVals),
               [](PayOff* p) { (*p)(value); });
std::transform(std::begin(v), std::end(v),
               std::begin(payVals),
               std::bind(&Payoff::operator(), _1, value); // using std::placeholders::_1

In C++03 you can use boost::bind instead of std::bind or if that is not available you can create your own functor or adapter functor that will call operator() on the argument.

If you are calling transform from your main function, this does not exist.

It looks as you should supply a double as follows (not a pointe as suggested above):

const double spot(99.);
transform(v.begin(), v.end(), payVals.begin(),  bind2nd(mem_fun(&PayOff::operator()),spot));

PS I have not checked your syntax but essentially this is how to do in pre-c++11 code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top