1

I have a class Alpha and a function pointFun which should accept both Alpha member functions and generic external functions (e.g.: defined in the main).

I have overridden pointFun to make it useable both by Alpha member functions and by external functions. But since pointFun function is actually very long I want to avoid to repeat it twice.

Is there a way to accept both function pointer types? I tried to do that (see the commented part of code) but it doesn't work.

// fpointer.h

#include <iostream>
using std::cout;
using std::endl;

class Alpha {
    public:
        Alpha() {}

        void pointFun (void (Alpha::*fun)());
        void pointFun (void (*fun)());
        //void pointFun (void (*funA)(), void (Alpha::*funB)()); // <-- how to make THIS instead of the previous two?
        void printA   ();
        void assignF  ();

    private:
         int value;
        bool set;
};

void Alpha::pointFun(void (Alpha::*fun)()) {
    (Alpha().*fun)();
}

void Alpha::pointFun(void (*fun)()) {
    (*fun)();
}

/* // I want this:
void Alpha::pointFun(void (*funA)() = 0, void (Alpha::*funB)() = 0) {
    (*funA)();
    (Alpha().*funB)();
    // same code, different pointer functions
}
*/

void Alpha::printA() {
    cout << "A" << endl;
    // some long code
}

void Alpha::assignF () {
    pointFun(&Alpha::printA);
}

And this is the main:

// MAIN.cpp

#include <iostream>
#include "fpointer.h"
using namespace std;

void printB() {
    cout << "B" << endl;
    // same long code as before
}

int main() {
    Alpha A;
    A.pointFun(printB);
    A.assignF();
}
Antonio Papalillo
  • 1,262
  • 13
  • 22

2 Answers2

1

Sure:

struct Foo
{
    using Fn = R(T1, T2, T3);

    R execute(Fn * f, T1 a1, T2 a2, T3 a3)
    //        ^^^^^^
    //        free pointer
    {
        return f(a1, a2, a3);
    }

    R execute(Fn Foo:: *f, T1 a1, T2 a2, T3 a3)
    //        ^^^^^^^^^^^
    //        pointer-to-member
    {
        return (this->*f)(a1, a2, a3);
    }

    // e.g.
    R you_can_call_me(T1, T2, T3);
};

R i_am_free(T1, T2, T3);

R dispatch(bool b, Foo & x, T1 a1, T2 a2, T3 a3)
{
    if (b) { x.execute(&i_am_free, a1, a2, a3); }
    else   { x.execute(&Foo::you_can_call_me, a1, a2, a3); }
}
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
1

You may create a method which takes a std::function and forward to it for your special case:

class Alpha {
public:
    void pointFun (std::function<void()> f); // Long function definition

    void pointFun (void (Alpha::*fun)()) { pointFun([this, fun](){(this->*fun)();}); }

// Other stuff
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • That would be amazing! But doesn't work for me: it says `[Error] 'fun' is not captured`. How to solve this? (It's referring to this portion of code: `(this->*fun)`) – Antonio Papalillo Jul 05 '15 at 12:04
  • 1
    @AndroidGuy: Sorry, forget to capture `fun`. Fixed now. – Jarod42 Jul 05 '15 at 14:20
  • Thank you, now it's perfect :D – Antonio Papalillo Jul 05 '15 at 14:44
  • I need to study better this method of passing variables. How it's called? I mean this: `pointFun([this, fun](){(this->*fun)();});` In particular I need to know how to pass a second variable to `pointFun` or pass a variable to `std::function f`. – Antonio Papalillo Jul 05 '15 at 15:26
  • 1
    @AndroidGuy: look at [lambda](http://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11) and lambda capture. – Jarod42 Jul 05 '15 at 16:07