views:

823

answers:

4

Okay I have a bit of a problem which i'm struggling to solve.

Basically I have an abstract functor class that overloads operator() and derived objects that implement it.

I have a function (part of another class) that tries to take an Array of these functor classes and tries to pass a pointer to a member function to the std algorithm for_each(), here is a overview of what i'm doing:

EDIT: I have re-cleand it and put the old small example for clarity.

class A{
  operator()(x param)=0;
  operator()(y param)=0;
}

class B: public A{
  operator()(x param); //implemented
  operator()(y param);
}
...// and other derived classes from A

void ClassXYZ::function(A** aArr, size_t aSize)
{
  ...//some code here

  for(size_t i = 0; i< aSize; i++){

    A* x = aArr[i];
    for(v.begin(), v.end(), ...//need to pass pointer/functor to right operator() of x here

..//other code
}

I've tried a few ways and I can't figure out how to get it to work, I need to use the abstract type as I could have different derived types but they will all have to implement the same operator()(param x) function.

I just need the for_each() function to be able to call the member function operator()(param x). I have a different function where it has concrete implementations and simply passes an instance of those and it works. I'm trying to achieve a similar effect here but without the knowledge of what concrete classes i'm given.

I don't know what i'm doing wrong but any help?

+1  A: 

The expression "bar.*fn" doesn't evaluate to regular, or non-member, function pointer. So you need to call a binding function (either std::tr1::bind or boost::bind ) to obtain such a function.

da_m_n
hmm i'll give that a try
iQ
+4  A: 

You want something like this...

std::for_each(
  it->second.begin(),
  it->second.end(),
  std::bind1st(std::mem_fun(&A::operator()),x)
);
alex tingle
whats the mem_fun for?
iQ
Nice. Also `bind1st()` from the regular C++03 standard will work in place of the more general `std::tr1::bind()` you have used here (which may not be supported by all compilers yet).
j_random_hacker
A nice example of how generic you can be with C++, but it's such a pain on the eyes. :-/
Frerich Raabe
mem_fun() converts a unary member function - called like obj->fun(arg) - into a binary normal function - called like fun(obj,arg).
alex tingle
That doesn't compile for me :( I get: error: no matching function for call to ‘mem_fun(<unresolved overloaded function type>)’|
iQ
I think it probably doesn't like the fact I have inheritance running through and the function is an overloaded operator.
iQ
Sounds like you need to resolve the overload. Get the function you want as a variable - `void (A::*fp)(param) = ` then pass it to mem_fun - `std::mem_fun(fp)`.
alex tingle
j_random_hacker
Gah! - j_random_hacker: We're swiftly degenerating to coding line noise.
alex tingle
yes thats exactly the problem, overloading! @alex I've tried that before but it didn't like it, something about typename operation and invalid cast from const A to A*, I will try static_cast by j_random.
iQ
@iQ: Alex's and my approaches are basically equivalent -- if his doesn't work, mine won't and vice versa. Your error must be from somewhere else. PLEASE post a complete snippet of the code you have, there are far too many problems (e.g. mismatched braces!) with your current one.
j_random_hacker
@alex: Yep, C++ gives you ample opportunity for that... ;)
j_random_hacker
Lol sorry I'll try and post the full code snippet, I just wanted to make it simple so i made the code up based on it. One sec I will do it.
iQ
+2  A: 

If I understand what you want to do, there are quite a few errors in your code snippet:

  • sizeof aArr is wrong, you need to pass the size explicitly (noticed by ChrisW)
  • Missing virtual specifier on the original declaration of operator()()
  • Not sure where your for loop ends as there's no matching } (I suspect it shouldn't be there at all)

Here's some code that will loop through an array of A (or A-derived) objects and call operator() on each one, passing across a passed-in argument as the param parameter:

#include <iostream>
#include <algorithm>
#include <functional>

using namespace std;

typedef double param;      // Just for concreteness

class A {
public:
    virtual void operator()(param x) = 0;
};

class B : public A {
public:
    void operator()(param x) { cerr << "This is a B!  x==" << x << ".\n"; }
};

void function(A** aArr, size_t n, param theParam) {
    void (A::*sFunc)(param x) = &A::operator();
    for_each(aArr, aArr + n, bind2nd(mem_fun(sFunc), theParam));
}

int main(int argc, char** argv) {
    A* arr[] = { new B(), new B(), new B() };

    function(arr, 3, 42.69);

    delete arr[0];
    delete arr[1];
    delete arr[2];
    return 0;
}

mem_fun() is necessary to convert a 1-parameter member function pointer to a 2-parameter function object; bind2nd() then produces from that a 1-parameter function object that fixes the argument supplied to function() as the 2nd argument. (for_each() requires a 1-parameter function pointer or function object.)

EDIT: Based on Alex Tingle's answer, I infer that you might have wanted function() to do many things on a single A-derived object. In that case, you'll want something like:

void function(A** aArr, size_t n, vector<param> const& params) {
    for (size_t i = 0; i < n; ++i) {
        void (A::*sFunc)(param x) = &A::operator();
        for_each(params.begin(), params.end(), bind1st(mem_fun(sFunc), aArr[i]));
    }
}
j_random_hacker
Yes i'll try that, since this is full standard c++. I do have virtual i just forgot to leave it out from example and i'll fix the size of arr as well. I'll post back if it works, should do.
iQ
With the for_each loop, it is actually working on a vector of some values. So i need the functors to act on those data. so the for_each(v.begin(), v.end(), func) where v is the vector and func is the pointer i'm trying to get out from the aArr
iQ
If you reread you might find I anticipated that... :) If not, let me know what needs changing.
j_random_hacker
Yeah i can't any of the solutions to work, I think i maybe doing something wrong on my part. As a general question how would you get a pointer to a member function if all your given is a pointer to an instance?
iQ
Do you realise that "pointer-to-member-function" is a different *category* of type than "pointer-to-function"? It is *not* possible to convert from one to the other. However you can get an object that can be called like a function from a combination of pointer-to-object and pointer-to-member-function using `bind1st(mem_fun(pMemFunc), pObj)`.
j_random_hacker
yep that's what i've been trying to do but I always get : error: no matching function for call to ‘mem_fun(<unresolved overloaded function type>) ---- so I thought i must be doing something wrong, I get a pointer to an object and i've tried passing the de referenced pointer and the pointer itself. No luck.
iQ
AHAA wait i'm re-editing my question, I know the source of the problem i think
iQ
A: 

I couldn't get it work using the current format, I think it doesn't like the fact i'm using a Pointer to a base member function and trying to call a derived classes implementation like that.

Instead I modified the code to include pure virtual functions in the base class that will return functors for each derived class when implemented. I can't think of anything else that would work. But it compiles like this.

But I am curious if anyone has a solution to the original problem without having to use pure virtual "create functor" methods in the base class.

iQ