AngusTheMan
AngusTheMan

Reputation: 582

callback in C++ struct

I have been trying to implement a callback function in c++. Within a class, I have a struct, a number of methods, and a method that creates an instance of the struct with one of the other methods as its argument.

The struct has many other variables, but an illustration is depicted here:

class MYCLASS
{
public:
    MYCLASS();

    struct TEST{
        std::function<int(int)> foo;
    };

    int plus(int x){
        return x + 1;
    }

    int minus(int x){
        return x - 1;
    }

    void sim(){
        TEST T;             // make an instance of TEST
        T.foo = plus(5);    // assign TEST.foo a function (plus or minus)  
        T.foo();            // call the method we assigned
    }
};

Within the sim method, I want to create an instance of test and give it either plus or minus, depending on some criterion. Both lines where I try and give the instance T a plus function and subsequently call it are incorrect.

Upvotes: 3

Views: 3382

Answers (2)

JeJo
JeJo

Reputation: 32852

Option - 1

If the member functions plus() and minus() are simple enough like you have shown, you can make them as lambda functions inside the struct TEST. Since the capture-less lambdas can be stored in typed function pointers, the following will do what you want. See live demo

#include <iostream>
class MYCLASS
{
    int m_var = 5; // just for demonstration
public:
    MYCLASS() = default;
    struct TEST
    {
        using fPtrType = int(*)(int);   // function pointer type
        const fPtrType foo1 = [](int x) { return x + 1; };  // plus function
        const fPtrType foo2 = [](int x) { return x - 1; };  // minus function
    };

    void sim()
    {
        TEST T;
        std::cout << "Answer from int PLUS(int): " << T.foo1(m_var) << std::endl;
        std::cout << "Answer from int MINUS(int): " << T.foo2(m_var) << std::endl;
    }
};

Option - 2

If the above alter a lot in your code, use typed function pointer again for member functions and do as follows; which will avoid unnecessary copying(by capturing) the class instance to the lambda and template instantiation and other performance issues comes along with std::function as well.

See live demo

#include <iostream>    
class MYCLASS
{
    using fPtrType = int(MYCLASS::*)(int); // class member function pointer type
public:
    MYCLASS() = default;
    struct TEST { fPtrType foo = nullptr; };

    int plus(int x) { return x + 1; }
    int minus(int x) { return x - 1; }

    void sim()
    {
        TEST T;
        T.foo = &MYCLASS::plus; // now you can
        std::cout << "Answer from int PLUS(int): " << (this->*T.MYCLASS::TEST::foo)(5) << std::endl;
                                                     //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ syntax would be a bit ugly
        // later same ptr variable for minus()
        T.foo = &MYCLASS::minus;
        int answer = (this->*T.MYCLASS::TEST::foo)(5);
        std::cout << "Answer from int MINUS(int): " << answer << std::endl;
    }
};

int main()
{
    MYCLASS obj;
    obj.sim();
    return 0;
}

Output:

Answer from int PLUS(int): 6
Answer from int MINUS(int): 4

Upvotes: 1

HugoTeixeira
HugoTeixeira

Reputation: 4884

If you want to delay the call to T.foo, then you could use a lambda like this:

    T.foo = [this](int x) { return plus(x); };
    T.foo(5);

Upvotes: 2

Related Questions