Friday, April 07, 2006

C++ : In a bind with function objects part II

So, this was my first attempt at the function object...

class doSomethingWithA :
public std:unary_function<A *, void>
void operator() (A *a)
std::string &name = a->GetName();
// Oh No! GetControlByName is a member of class B!
Control *control = GetControlByName(name);
// so can’t use control here
bool value =
control->GetCurrentValue() > a->GetThreshold();
// graphic comes from class B too!

When I started to write this function object I was feeling pretty proud of myself, but as they say, pride comes before a fall and I immediately fell over on the second line of the overloaded operator() method (i.e. the bit that gives an instance of this class function syntax making it a function object with the signature we want). There’s no way to call the methods I need as they are part of class B, the owner of this container. Ok, so I guess I need to pass in a reference to an object of class B?

Unfortunately, the methods of class B which I needed were declared private, so short of changing the accessibilty (shudder) of these I was pretty stuck. It was at this point that I begun to think that perhaps this std::for_each algorithm wasn’t very useful? After all my first version of Update() using a for-loop worked with no head scratching at all. Then again, for-loops themselves used to be a mystery once upon a time (really?) so on I soldiered.

Right, what to do? I did a quick bit of online research thinking that perhaps I could pass a member function of class B as the third parameter of std::for_each and found this useful little function adaptor:

template<class Result, class Type>
std::mem_fun_t<Result, Type>
std::mem_fun(Result (Type::*pm)());

Sounds like a jovial name doesn’t it? “Mem Fun” implies it does something amusing with memory but it actually stands for “Member Function”, this function takes a pointer to a member function and returns a function object. Just the ticket I thought so I rushed in and started to implement the member function of class B that could use all the lovely private methods and data it needed to. A quick glance at the usage of std::mem_fun and I realised my mistake:

class T
T(int v) : m_v(v) {}
void print() const
cout << m_v;
int m_v;

vector<T> arr;

std::for_each(arr.begin(), arr.end(), std::mem_fun(&T::print));

Using std::mem_fun like this only works with a member function of the class you are using in std::for_each! This makes sense because in order to call a member function pointer you need an object as well and the only objects used in the std::for_each algorithm are the ones it gets from the first iterator parameter. Undeterred I had a sudden brainwave!

Find out what it was in part III

No comments: