开发者

passing member functions as parameters / c++

I would like to implement, in c++, a class b where it would be possible to do some kind of iteration through a member set encapsulating the type of that iterator. Like:

b_object.for_each_x_do(function_f);

so function_f would get every开发者_开发知识库one of the x members and do anything. Let's say:

void function_f(x_member_type x){ cout << x << endl; }

Ok. So I'm trying to achieve that through a code like:

class b{
    int *x;
public:
    void foreach_x_do(void (*f)(int)){
            while(*x++)  // or any kind of iteration through x
                    f(*x);
    }
};

class a{
    b b_inst;
public:
    void f(int x) {  }     
    a(){
            b_inst.foreach_x_do(f); // by mistake it was b_inst.foreach_x_do(f)(), however this wasn't the point at all. 
    }
    ~a(){}
};

int main(){} 

However, I'm getting this error, compile-time:

fp.cpp: In constructor ‘a::a()’:

fp.cpp:17: error: no matching function for call to ‘b::foreach_x_do(<unresolved overloaded function type>)’

fp.cpp:6: note: candidates are: void b::foreach_x_do(void (*)(int))

Anybody can help getting it to compile?


As @steveo225 noted, f in that context is of type void (a::*)(int) rather than void (*)(int). There are two approaches to fixing this -- the first is to make b::foreach_x_do a member function template that takes any callable type:

class b {
    int* x;

public:
    b() : x() { }
    template<typename F>
    void foreach_x_do(F f) {
        while(*x++)
            f(*x);
    }
};

class a {
    b b_inst;

public:
    void f(int x) { }
    a() : b_inst() {
        b_inst.foreach_x_do(std::bind(&a::f, this, _1));
    }
};

The second is to keep b::foreach_x_do a non-template and have it take a std::function<> instead of a function pointer:

class b {
    int* x;

public:
    b() : x() { }
    void foreach_x_do(std::function<void(int)> const& f) {
        while(*x++)
            f(*x);
    }
};

class a {
    b b_inst;

public:
    void f(int x) { }
    a() : b_inst() {
        b_inst.foreach_x_do(std::bind(&a::f, this, _1));
    }
};

In either case, replace std::bind and std::function with their boost:: counterparts if your compiler is too old to ship with std:: or std::tr1:: implementations. Also note that if you have a C++11 compiler, you can use a lambda instead of bind.


It should just be:

b_inst.foreach_x_do(f);

You also need to make f static, not a non-static member method since the original signature for your foreach_x_do function is for a stand-alone function pointer, not a pointer-to-member-function. So i.e.,

static void f(int x) {  } 


The function for_each_x_do is expecting a function pointer, while you're (trying) to give it a member function pointer. The two are not the same. The former can be called directly, while the latter requires an object instance to be called. I'd suggest you use std::function or boost::function instead. Something like:

void for_each_x_do(function<void (int)> f) {
  // your code here
}

And then use a binder to construct a function object:

a(){
  b_inst.foreach_x_do(bind(&a::f, this, _1));     
}


In this line:

 b_inst.foreach_x_do(f)();

Remove the second set of parenthesis; you don't need them.

 b_inst.foreach_x_do(f);

should work fine.


f() is a member function -- so it's relevance is limited to it's corresponding object. Some of these solutions so far won't work.

You have two choices, either make the function static, in which case it doesn't matter which object, or somehow also pass the object.

The second method is clearly explained in this helpful FAQ specifically about passing member functions.


Try:

class b{
int *x;
public:
void foreach_x_do(void (*f)(int)){
        while(*x++)  // or any kind of iteration through x
                (*f)(*x);
}

};

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜