【问题标题】:Duplicate issue with callbacks回调的重复问题
【发布时间】:2021-11-11 10:16:09
【问题描述】:

我有以下代码,我想知道如何解决 33-38 和 47-52 行的重复问题。 struct X 有 2 个具有相同签名的方法,Y 有一个 X 的实例,并且有 2 个方法必须使用相同的回调,该回调必须为 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;
}

【问题讨论】:

  • 一开始为什么会有重复的代码?不需要重复的功能。
  • 33-38 和 47-52 被 SONAR 标记为重复

标签: c++ duplicates c++14


【解决方案1】:

标准解决方案怎么样 - 添加一个间接级别?

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++; }
};

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++; };
    };
};

【讨论】:

【解决方案2】:

这比预期的要困难一些,因为您在 2 个函数中捕获不同的变量。

您可以将std::bind 与一个函数一起使用:

#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

你也可以std::bind给一个成员函数:https://godbolt.org/z/f9snPbKeW

【讨论】:

  • 谢谢!我宁愿不使用 std::bind
  • @Scheff'sCat 您应该将其发布为答案。我会赞成。
【解决方案3】:

我必须承认我一直讨厌 bind() 这样的东西,因为我首先结合 sigc++ 学习它们。 (我永远记不起应用它们的正确顺序,尤其是与 hide() 结合使用时。)

随着 lambdas 的引入,所有的麻烦都立即解决了(我很快就成为了 lambdas 的粉丝)。

反过来,lambda 类似于函数或仿函数。因此,要添加到mch's answer,可以将 lambda 转换为嵌入到 OP 中的可重用函子 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-17
    • 1970-01-01
    • 2017-01-18
    • 2017-10-29
    • 1970-01-01
    • 2012-10-12
    相关资源
    最近更新 更多