1

Take the following as a example: (Note, the example doesn't work, but it should be enough to illustrate what I am trying to do)

class Point {
    float x, y;
public:
    float getX() const { return x; }
    float getY() const { return y; }
};

class Polygon {
    std::vector<Point> points;

    std::vector<float> get(float (Point::*func)()const) {
        std::vector<float> ret;
        for(std::vector<Point>::iterator it = points.begin(); it != points.end(); it++) {
            // call the passed function on the actual instance
            ret.push_back(it->*func());
        }
        return ret;
    }

public:
    std::vector<float> getAllX() const {
        return get(&Point::getX); // <- what to pass for getX
    }
    std::vector<float> getAllY() const {
        return get(&Point::getY); // <- what to pass for getY
    }
};

EDIT:

The problem was order of operations; the compiler required parenthesis around the call as such:

(it->*func)()
steveo225
  • 11,394
  • 16
  • 62
  • 114

2 Answers2

2

It looks like you want to use a "pointer to a member function", which uses the following syntax:

class Point {
    float x, y;
public:
    float getX() const { return x; }
    float getY() const { return y; }
};

class Polygon {
    std::vector<Point> points;

    std::vector<float> get(float (Point::*func)()) { // !!! NEW SYNTAX - POINTER TO MEMBER
        std::vector<float> ret;
        for(std::vector<Point>::iterator it = points.begin(); it != points.end(); it++) {
            // call the passed function on the actual instance
            ret.push_back((it->*func)()); // !!! ADDED PARENTHESES
        }
        return ret;
    }

public:
    std::vector<float> getAllX() const {
        return get(&Point::getX); // !!! POINTER TO MEMBER
    }
    std::vector<float> getAllY() const {
        return get(&Point::getY); // !!! POINTER TO MEMBER
    }
};

Disclaimer: Untested.

Also, you might want to look into the <functional> library in C++11; it's very nice for things like this.

This is how I might personally approach the situation:

#include <functional>
#include <vector>
#include <algorithm>

class Point {
    float x, y;
public:
    float getX() const { return x; }
    float getY() const { return y; }
};

class Polygon {
    std::vector<Point> points;

    std::vector<float> get(std::function<float(const Point&)> func) const {
        std::vector<float> ret(points.size());
        std::transform(points.begin(), points.end(), ret.begin(), func);
        return ret;
    }

public:
    std::vector<float> getAllX() const {
        return get(std::mem_fn(&Point::getX));
    }

    std::vector<float> getAllY() const {
        return get(std::mem_fn(&Point::getY));
    }
};

Disclaimer: Compiles, but untested.

Apples
  • 3,135
  • 1
  • 21
  • 26
  • Tried that. Compile errors. Although this lead me to the real problem: order of operations. Updated in question. – steveo225 Apr 15 '13 at 16:52
1

Changed lot of stuff in your program. Pointer to member syntax is not exactly the same as pointer to function syntax.

I have used a typedef and a macro from the C++ to simplify this

http://www.parashift.com/c++-faq/typedef-for-ptr-to-memfn.html

http://www.parashift.com/c++-faq/macro-for-ptr-to-memfn.html

class Point {
    float x, y;
public:
    float getX() const { return x; }
    float getY() const { return y; }
};

// This typedef makes is easier to declare a pointer to a member method
typedef float (Point::*PointPtr)() const;
// This macro makes it easier to call through a member function pointer.
#define CALL_MEMBER_FN(object,ptrToMember)  ((object).*(ptrToMember))

class Polygon {
    std::vector<Point> points;

    // Made this a const function. And changed the parameter type.
    std::vector<float> get(PointPtr func) const {
        std::vector<float> ret;

        // Made this a const iterator
        for(std::vector<Point>::const_iterator it = points.begin(); it != points.end(); it++) {
            // Changed the call to use the macro
            ret.push_back(CALL_MEMBER_FN((*it), func)());
        }
        return ret;
    }

public:
    std::vector<float> getAllX() const {
        return get(&Point::getX); 
    }
    std::vector<float> getAllY() const {
        return get(&Point::getY;);
    }
};

Explained the changes in the comments.

user93353
  • 13,733
  • 8
  • 60
  • 122
  • That is correct, although it can be done more concisely by just adding parenthesis as I noted in the edit to the question. Thanks – steveo225 Apr 15 '13 at 16:57
  • @steveo225 - well, the macro and the typedef help you avoid making the error you made in the original question. – user93353 Apr 15 '13 at 16:59