Home > Net >  Duplicate issue with callbacks
Duplicate issue with callbacks

Time:11-11

I have the following code and I want to know how duplicate issue for lines 33-38 with 47-52 cand be solved. struct X has 2 methods with same signature and Y has an instance of X and has 2 methods which has to use the same callback which has to capture same values for the methods from X.

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

struct X 
{
   void func(std::function<void(int)>f, int x)
   {
       f(x);
   }
   
    void func2(std::function<void(int)>f, int x)
   {
       f(x);
   }
};

struct Y 
{
    void doSomething_1()
    {
        int x = 10;
        bool called = false;
        x_.func(
        [&x, &called](int xx)      // line 33
        {                          // line 34
            called = true;         // line 35
            x  ;                   // line 36
            xx  ;                  // line 37
        }                          // line 38
        , 20);
    }
    
    void doSomething_2()
    {
        int x = 10;
        bool called = false;
        x_.func2(
        [&x, &called](int xx)   // line 47
        {                       // line 48
            called = true;      // line 49
            x  ;                // line 50
            xx  ;               // line 51
        }                       // line 52
        , 20);
    }
    
    X x_;
};


int main()
{
    Y y;
    y.doSomething_1();
    y.doSomething_2();
    
    return 0;
}

CodePudding user response:

How about The Standard Solution – add a level of indirection?

struct Y 
{
    void doSomething_1()
    {
        int x = 10;
        bool called = false;
        x_.func([this, &x, &called](int xx) { wrapper(x, called, xx); }, 20);
    }
    
    void doSomething_2()
    {
        int x = 10;
        bool called = false;
        x_.func([this, &x, &called](int xx) { wrapper(x, called, xx); }, 20);
    }
    
    X x_;
    
    void wrapper(int&x, bool& called, int xx) { called = true; x  ; xx  ; }
};

or

struct Y 
{
    void doSomething_1()
    {
        int x = 10;
        bool called = false;
        x_.func(wrapper(x, called), 20);
    }
    
    void doSomething_2()
    {
        int x = 10;
        bool called = false;
        x_.func(wrapper(x, called), 20);
    }
    
    X x_;
    
    std::function<void(int)> wrapper(int&x, bool& called)
    {
        return [&x, &called](int xx) {called = true; x  ; xx  ; };
    };
};

CodePudding user response:

It is a little bit more difficult than expected, because you are capturing different variables in the 2 functions.

You can use std::bind with a function for that:

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

struct X 
{
   void func(std::function<void(int)>f, int x)
   {
       f(x);
   }
   
    void func2(std::function<void(int)>f, int x)
   {
       f(x);
   }
};

void your_func(int xx, bool &called, int &x)
{
    called = true;
    x  ;
    xx  ;
}

struct Y 
{
    
    void doSomething_1()
    {
        int x = 10;
        bool called = false;
        auto func = std::bind(&your_func, std::placeholders::_1, called, x);
        x_.func(func, 20);
    }
    
    void doSomething_2()
    {
        int x = 10;
        bool called = false;
        auto func = std::bind(&your_func, std::placeholders::_1, called, x);
        x_.func2(func, 20);
    }
    
    X x_;
};


int main()
{
    Y y;
    y.doSomething_1();
    y.doSomething_2();
    
    return 0;
}

https://godbolt.org/z/5ee5ehcsh

You can also std::bind to a member function: https://godbolt.org/z/f9snPbKeW

CodePudding user response:

I must admit that I always hated things like bind() since I learnt them first in combination with sigc . (I never could remember the correct order to apply them, especially if combined with hide().)

With the introduction of lambdas, all the trouble was gone immediately (and I soon became a fan of lambdas).

A lambda in turn just resembles a function or functor. So, to add to mch's answer, the lambda could be turned into a re-usable functor which is embedded into OPs class Y:

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

struct X 
{
   void func(std::function<void(int)>f, int x)
   {
       f(x);
   }
   
    void func2(std::function<void(int)>f, int x)
   {
       f(x);
   }
};

struct Y 
{
    struct Count {
        int& x;
        bool& called;
    
        Count(int& x, bool& called): x(x), called(called) { }
        void operator()(int xx)    // line 33
        {                          // line 34
            called = true;         // line 35
            x  ;                   // line 36
            xx  ;                  // line 37
        }
    };
        
    void doSomething_1()
    {
        int x = 10;
        bool called = false;
        x_.func(Count(x, called), 20);
    }
    
    void doSomething_2()
    {
        int x = 10;
        bool called = false;
        x_.func2(Count(x, called), 20);
    }
    
    X x_;
};


int main()
{
    Y y;
    y.doSomething_1();
    y.doSomething_2();
    
    return 0;
}

Live Demo on coliru

  • Related