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