2

I don't have much experience using array of functions in C++. I need to use an array of functions where the array contains functions from different objects. Here is some dummy code to illustrate what I want to implement.

class base_class
{
public:
  virtual int function1(int arg1, int arg2);
  virtual int function2(int arg1, int arg2);
};

class derived_class : public base_class
{
public:
  int function1(int arg1, int arg2) { /* ... */ };
  int function2(int arg1, int arg2) { /* ... */ };
  // ...
};

typedef int (*functions) (int arg1, int arg2); 

int main()
{
  derived_class object1;  
  derived_class object2;  

  functions func_instance[4];
  func_instance[0] = object1.function1;
  func_instance[1] = object1.function2;
  func_instance[2] = object2.function1;
  func_instance[3] = object2.function2;
  // ...
}

I can't get it to work, it throws following error:

error: argument of type int () (int , int) does not match int (*) (int, int)
2
  • 2
    Look up std::function and std::bind. Commented May 14, 2013 at 7:16
  • Welcome to SO. Please have a look at stackoverflow.com/faq to understand how the site works. Please mark the best answer to your question as accepted and up-vote accordingly. Have fun :) Commented May 14, 2013 at 21:52

1 Answer 1

9

The easiest way is to use std::function and std::bind.

#include <functional>
#include <array>

derived_class object1;
derived_class object2;

std::array< std::function<int(int, int)>, 2> > 
  arr = {{ std::bind(&derived_class::function1, &object1)
         , std::bind(&derived_class::function2, &object1)}};
         // and so on

Note that object1 and object2 have been bound by address. You need to keep them alive as long as the bound functions are alive. If you just write object1 in the bind expression a copy of the object will be stored in the bound function and no scope problems will occur.

C++03 A complete example with a hand-rolled, single-purpose binder-type:

#include <iostream>

struct base
{
  virtual void f0() { std::cout << "f0 base" << std::endl; }
  virtual void f1() { std::cout << "f1 base" << std::endl; }
};

struct derived : base
{
  void f0() { std::cout << "f0 derived" << std::endl; }
  void f1() { std::cout << "f1 derived" << std::endl; }
};

// typedef for a Pointer to a member function 
// of base that accepts arguments and returns void
typedef void (base::*MemberPtrType)(void);

// we pack a pointer to a class and a pointer to a member function together
struct binder
{
  MemberPtrType ptr;
  base*         base;

  // shortcut to call this thing, you might also want 
  // to have an overload of operator() and a result_type typedef
  void call()
  { ((base)->*(ptr))(); }
};


int main()
{
  base b;
  derived d;

  // initialize a 4 element array of binder, the first argument is the function,
  // the second is the object to call it on
  // 
  // remember that b and d need to be alive as long as 
  // you want to call something in this array
  binder arr[4] = { {&base::f0, &b}, {&base::f1, &b}, 
                    {&base::f0, &d}, {&base::f1, &d}};

  // now walk through the array and call each
  for(binder* begin = arr; begin != arr + 4; ++begin)
  {
    begin->call();
  }


  return 0;
}
Sign up to request clarification or add additional context in comments.

7 Comments

thanks for the suggestion, I tried to adopt this, GCC 4.1.2 does not not have the 'array' header (?). I have to use this compiler. Is there any alternative solution?
@functon It wont have functional either. Your alternatives include using the Boost libraries or doing it the painful way. I try to come up with a C++03 solution. But those can be harder to write and maintain then just not doing it at all...
@functon I added a C++03 example.
@pmr Well, technically it will have the functional header, just not the std::function type. But sorry for the nitpicking and +1 for the answer.
@ChristianRau Of course. C++03 functional was so useless that I don't even remember it existed.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.