Sunday, April 19, 2009

using array of pointer to member function

Seems like a crazy at the first instance, but this is an amazing use of the facility provided by C++ which is called, pointer to member of a class. This can be a function or a variable. But where to use it. Well one of cases is when one needs to call different function of same signature based on some parameter. Surely this can be done via other trivial means as well certain situation may call for special measures. This can used in that case.

How to create and use it is taken straight out of C++ FAQLite . Link to specific page is here.

Say we have a class A as following

class A
{
public : 
    void a(int x);
    void b(int x);
    void c(int x);
    void d(int x);
}

//create array of pointer to member function
int ((A::*ptr)[4])(int x) = {&A::a, &A::b, &A::c, &A::d};

//using it in function
void testFunc(int val1, int val2)
{
    ObjectOfA.*(ptr[val1])(val2);
}

So our testfunction will call a,b,c or d from ObjectOfA depending on the val1 with parameter val2. Though obviously there are better ways to do it, but then this is also one complicated but shorter(codewise) one.

3 comments:

Christopher Currie said...

Cool technique. You might also try using some of the TR1 features to make the array easier to use. For example, you can abstract away the pointer-to-member by using std::tr1::function:

// create array of member function
std::tr1::array<
  std::tr1::function<void (A&,int)>, 4
> ptr = {&A::a,&A::b,&A::c,&A::d};

// using it in function
void testFunc(int val1,int val2)
{
  ptr[val1]( ObjectOfA, val2 );
}


In addition, you can bind the array to a specific instance of A, using std::tr1::bind:

// binding to a specific A
using std::tr1::placeholders::_1;

std::tr1::array<
  std::tr1::function<void(int)>, 4
> ptr2 = {
  std::tr1::bind( &A::a, ObjectOfA, _1 ),
  std::tr1::bind( &A::b, ObjectOfA, _1 ),
  std::tr1::bind( &A::c, ObjectOfA, _1 ),
  std::tr1::bind( &A::d, ObjectOfA, _1 )
};

// using it in a function
void testFunc2(int val1,int val2)
{
  ptr2[ val1 ]( val2 );
}

Good post, I look forward to reading more.

100rabh™ said...

This is something that I have no clue about. But seems like interesting thing to know more about. Thanks for this amazing example.

Anonymous said...

int (A::*ptr[4])(int x) = {&A::a, &A::b, &A::c, &A::d};

(ObjectOfA.*ptr[val1])(val2);