C++ Reference to member function work around (computation speed)

54 views Asked by At

It is well known that you cannot create a reference to a member function in C++ [source].

For those that don't know. The issue come when you want to do something similar to

class A
{
public:
    void Add(int a, int b)
    {
        std::cout << "Sum is " << a + b << std::endl;
    }

    void CallAdd(int a, int b, void (*func)(int, int))
    {
        func(a, b);
    }
};

and then call Add through CallAdd:

A a;
a.Add(3, 7); // This works fine
a.CallAdd(3, 7, &a.CallAdd); //This does not compile

The error is

error: cannot create a non-constant pointer to member function
    a.CallAdd(3, 7, &a.CallAdd);

Which would not occur if it wiere outside a class. There is a work around using std::function/lambda. Like this:

class A
{
public:
    function<void(int, int)> AddFunc = [](int a, int b)
    {
        std::cout << "Sum is " << a + b << std::endl;
    };

    void CallAdd(int a, int b, std::function<void(int, int)> &func)
    {
        func(a, b);
    };
};

int main()
{
    A a;
    a.CallAdd(3, 7, a.AddFunc);
}

This works fine but the problem is that computation time increases a lot (obviously this is just a minimal reproducible example) compared to simply calling the function.

Is there a way to increase computation speed or is this the best one can do?

For context, I have an algorithm to integrate functions, and I want to change integrands at will so the integrand must be a function parameter.

1

There are 1 answers

0
MarkB On

Pass the function object (or lambda) to a templated member function as follows:

#include <concepts>
#include <iostream>

inline auto myAddFunc = [](int a, int b) {
    std::cout << "Sum is " << a + b << std::endl;
};

class A
{
public:
    template <std::regular_invocable<int,int> Func>
    void CallFunc(int a, int b, Func func)
    {
        func(a, b);
    };
};

int main()
{
    A a;
    auto mySubFunc = [](int a, int b) {
        std::cout << "Difference is " << a - b << std::endl;
    };
    a.CallFunc(3, 7, myAddFunc);
    a.CallFunc(7, 3, mySubFunc);
}