drbombe
drbombe

Reputation: 639

How to pass a function in a class as a parameter to another function in the same class in C++11?

The following minimalist codes are used to illustrate my question. Those codes do not compile. How can I use lambda expression or std::bind to pass a function member as a parameter? Many thanks for your help

#include <iostream>

using namespace std;
class ABC{
private:
    int x =3;
    int add2num(int a, int b){
        return a+b+x;
    }

    int worker(int &fun(int a, int b), int a, int b){
        return fun(a,b);
    }
public:
    int doSomething(int a, int b){
        return worker(add2num, a, b);
    }
};

int main() {
    ABC test;
    cout << test.doSomething(3,5) << endl;
    return 0;
}

Upvotes: 4

Views: 284

Answers (5)

8znr
8znr

Reputation: 346

This would be a comment to paweldac answer but I've not enough reputation.

A better lambda would be initialized using 'this' in the capture list (see http://en.cppreference.com/w/cpp/language/lambda):

int doSomething(int a, int b)
{
    auto func = [this](int a, int b) -> int { return add2num(a,b); };
    return worker(func, a, b);
}

Additionally, in this way the lambda is initialized every time doSomething is called. As you do not need this you can consider a way to initialize func just once.

Upvotes: 0

Michał Walenciak
Michał Walenciak

Reputation: 4369

You can achieve your goal without a lambda or std::bind like this:

#include <iostream>

using namespace std;
class ABC{
private:
    int x =3;
    int add2num(int a, int b){
        return a+b+x;
    }

    int worker(int (ABC::*fun)(int a, int b), int a, int b){
        return (this->*fun)(a,b);
    }
public:
    int doSomething(int a, int b){
        return worker(&ABC::add2num, a, b);
    }
};

int main() {
    ABC test;
    cout << test.doSomething(3,5) << endl;
    return 0;
}

Compare this code against yours to see differences.

Here you can read more about pointers to members etc.

Upvotes: 4

ABu
ABu

Reputation: 12259

Using lambdas and templates:

#include <iostream>
#include <functional>

using namespace std;
class ABC{
private:
    int x =3;
    int add2num(int a, int b){
        return a+b+x;
    }

   template<class functor_t>
   int worker(const functor_t& fun, int a, int b){
       return fun(a,b);
   }

public:
   int doSomething(int a, int b) {
     return worker([this](int a, int b){ return add2num(a, b); }, a, b);
   }

};

int main() {
    ABC test;
    cout << test.doSomething(3,5) << endl;
    return 0;
}

Or, without lambdas but using std::bind:

   int doSomething(int a, int b) {
     namespace ph = std::placeholders;

     return worker(std::bind(&ABC::add2num, this, ph::_1, ph::_2), a, b);
   }

The rest of the code doesn't need to be touch, since worker is still a template, and thus accepts any callable type.

Upvotes: 4

roalz
roalz

Reputation: 2778

One possible way, using std::bind and std::function (C++11):

#include <iostream>
#include <functional>
using namespace std::placeholders;

class ABC
{
private:
    int x = 3;

    int add2num(int a, int b)
    {
        return a+b+x;
    }

    int worker(std::function<int(int, int)> fun, int a, int b)
    {
        return fun(a, b);
    }

public:
    int doSomething(int a, int b)
    {
        return worker(std::bind(&ABC::add2num, this, _1, _2), a, b);
    }
};

int main()
{
    ABC test;
    std::cout << test.doSomething(3,5) << std::endl;
    return 0;
}

Available on Ideone.

Output: 11

Upvotes: 1

paweldac
paweldac

Reputation: 1184

Adapted your code snippet to use lambda functions

#include <iostream>
#include <functional>

using namespace std;
class ABC{
private:
    int x =3;
    int add2num(int a, int b){
        return a+b+x;
    }

   int worker(std::function<int(int, int)> fun, int a, int b){
       return fun(a,b);
   }
public:
   int doSomething(int a, int b){
     auto func = [&](int a, int b) -> int { return add2num(a,b); };
     return worker(func, a, b);
   }
};

int main() {
    ABC test;
    cout << test.doSomething(3,5) << endl;
    return 0;
}

Here is ideone version: https://ideone.com/cupxaB

Upvotes: 1

Related Questions