如何将 class 方法作为参数传递给另一个函数,然后调用它,最好使变量 class 方法签名显式?
How can I pass a class method as a parameter to another function and later call it, preferably making the variable class method signature explicit?
如果我有一个 class 需要使用 class 方法作为参数调用父 class 方法,我可以使用 std::function
+ std::bind
如下图:
class A {
void complexMethod(std::function<void()> variableMethod) {
// other stuff ...
variableMethod();
// some other stuff..
}
}
class B : public A {
void myWay() {
// this and that
}
void otherWay() {
// other and different
}
void doingSomething() {
// Preparing to do something complex.
complexMethod(std::bind(&B::myWay, this));
}
void doingAnotherThing() {
// Different preparation to do some other complex thing.
complexMethod(std::bind(&B::otherWay, this));
}
}
我需要如何更改上述代码才能使用模板而不是 std::function
+ std::bind
来实现相同的功能?
用 lambda 代替 std::function
+ std::bind
怎么样?我仍然想调用 B:myWay()
和 B::otherWay()
但使用 lambda。我不想用 lambda 替换 B:myWay()
和 B::otherWay()
。
是否有任何实现技术(上述之一或其他一些)可以使 variableMethod
return 类型和参数显式化?我该怎么做?假设 variableMethod
的签名是:
bool variableMethod(int a, double b);
推荐哪种技术?为什么(速度、灵活性、易用性...)?
模板+lambda解决方案:
struct A
{
template <typename F>
void runA(F func)
{
cout << 1 << endl;
func();
cout << 3 << endl;
}
};
struct B : A
{
int number = 2;
void runnable() { cout << number << endl; }
void runB()
{
cout << 0 << endl;
runA([this]() { runnable(); });
cout << 4 << endl;
}
};
int main()
{
B variable;
variable.runB();
}
为了将函数作为模板参数,只需像上面那样接收该函数的模板类型即可。 lambdas 可以用来代替 bind 使事情变得更容易(this
被传递到 lambda 捕获列表)。
明确声明参数:
void run_func(std::function<bool(int, double)> func)
{
bool b = func(10, 10.01);
}
std::function
允许您像上面那样定义论点和 return 类型。
How would I need to change the above code to implement the same thing
using templates instead of std::function
+ std::bind
?
And how about lambdas instead of std::function
+ std::bind
? I
still want to call B:myWay()
and B::otherWay()
but using lambdas.
I don't want to substitute B:myWay()
and B::otherWay()
with
lambdas.
你可以使用 lambda,是的。
类似 [this]() { return myWay(); }
的东西:
- 捕获
this
,并且
- 调用当前object的一个方法。
#include <iostream> // cout
class A {
protected:
template <typename F>
void complexMethod(F&& f) { f(); }
};
class B : public A {
void myWay() { std::cout << "myWay\n"; }
void otherWay() { std::cout << "otherWay\n"; }
public:
void doingSomething() {
complexMethod([this]() { return myWay(); });
}
void doingAnotherThing() {
complexMethod([this]() { return otherWay(); });
}
};
int main() {
B b{};
b.doingSomething();
b.doingAnotherThing();
}
// Outputs:
//
// myWay
// otherWay
Is there any implementation technique (one of the above or some other)
were I would be able to make variableMethod
return type and
parameters explicit? How would I do it?
您可以使用 const std::function<bool(int,double)>& f
作为接收 complexMethod
函数的参数。并且仍然传递一个 lambda。请注意,尽管 lambda 表达式现在正在接收 (int i, double d)
(也可能是 (auto i, auto d)
)。
#include <functional> // function
#include <ios> // boolalpha
#include <iostream> // cout
class A {
protected:
bool complexMethod(const std::function<bool(int,double)>& f, int i, double d)
{ return f(i, d); }
};
class B : public A {
bool myWay(int a, double b) { return a < static_cast<int>(b); }
bool otherWay(int a, double b) { return a*a < static_cast<int>(b); }
public:
bool doingSomething(int a, double b) {
return complexMethod([this](int i, double d) {
return myWay(i, d); }, a, b);
}
bool doingAnotherThing(int a, double b) {
return complexMethod([this](auto i, auto d) {
return otherWay(i, d); }, a, b);
}
};
int main() {
B b{};
std::cout << std::boolalpha << b.doingSomething(3, 5.5) << "\n";
std::cout << std::boolalpha << b.doingAnotherThing(3, 5.5) << "\n";
}
// Outputs:
//
// true
// false
请注意,同样可以使用模板完成,尽管您不会使签名显式。
#include <functional> // function
#include <ios> // boolalpha
#include <iostream> // cout
class A {
protected:
template <typename F, typename... Args>
auto complexMethod(F&& f, Args&&... args) -> decltype(f(args...))
{ return f(args...); }
};
class B : public A {
bool myWay(int a, double b) { return a < static_cast<int>(b); }
bool otherWay(int a, double b) { return a*a < static_cast<int>(b); }
public:
bool doingSomething(int a, double b) {
return complexMethod([this](auto i, auto d) {
return myWay(i, d); }, a, b);
}
bool doingAnotherThing(int a, double b) {
return complexMethod([this](auto i, auto d) {
return otherWay(i, d); }, a, b);
}
};
int main() {
B b{};
std::cout << std::boolalpha << b.doingSomething(3, 5.5) << "\n";
std::cout << std::boolalpha << b.doingAnotherThing(3, 5.5) << "\n";
}
// Outputs:
//
// true
// false
Which technique is recommended? Why (speed, flexibility,
readility...)?
Scott Meyer 的 Effective Modern C++ 一书的第 34 项标题为 Prefer lambdas to std::bind
。它以一句话总结结束:Lambdas are more readable, more expressive, and may be more efficient than using std::bind
。但是,它也提到了 std::bind
可能比 lambda 有用的情况。
如果我有一个 class 需要使用 class 方法作为参数调用父 class 方法,我可以使用 std::function
+ std::bind
如下图:
class A {
void complexMethod(std::function<void()> variableMethod) {
// other stuff ...
variableMethod();
// some other stuff..
}
}
class B : public A {
void myWay() {
// this and that
}
void otherWay() {
// other and different
}
void doingSomething() {
// Preparing to do something complex.
complexMethod(std::bind(&B::myWay, this));
}
void doingAnotherThing() {
// Different preparation to do some other complex thing.
complexMethod(std::bind(&B::otherWay, this));
}
}
我需要如何更改上述代码才能使用模板而不是 std::function
+ std::bind
来实现相同的功能?
用 lambda 代替 std::function
+ std::bind
怎么样?我仍然想调用 B:myWay()
和 B::otherWay()
但使用 lambda。我不想用 lambda 替换 B:myWay()
和 B::otherWay()
。
是否有任何实现技术(上述之一或其他一些)可以使 variableMethod
return 类型和参数显式化?我该怎么做?假设 variableMethod
的签名是:
bool variableMethod(int a, double b);
推荐哪种技术?为什么(速度、灵活性、易用性...)?
模板+lambda解决方案:
struct A
{
template <typename F>
void runA(F func)
{
cout << 1 << endl;
func();
cout << 3 << endl;
}
};
struct B : A
{
int number = 2;
void runnable() { cout << number << endl; }
void runB()
{
cout << 0 << endl;
runA([this]() { runnable(); });
cout << 4 << endl;
}
};
int main()
{
B variable;
variable.runB();
}
为了将函数作为模板参数,只需像上面那样接收该函数的模板类型即可。 lambdas 可以用来代替 bind 使事情变得更容易(this
被传递到 lambda 捕获列表)。
明确声明参数:
void run_func(std::function<bool(int, double)> func)
{
bool b = func(10, 10.01);
}
std::function
允许您像上面那样定义论点和 return 类型。
How would I need to change the above code to implement the same thing using templates instead of
std::function
+std::bind
?And how about lambdas instead of
std::function
+std::bind
? I still want to callB:myWay()
andB::otherWay()
but using lambdas. I don't want to substituteB:myWay()
andB::otherWay()
with lambdas.
你可以使用 lambda,是的。
类似 [this]() { return myWay(); }
的东西:
- 捕获
this
,并且 - 调用当前object的一个方法。
#include <iostream> // cout
class A {
protected:
template <typename F>
void complexMethod(F&& f) { f(); }
};
class B : public A {
void myWay() { std::cout << "myWay\n"; }
void otherWay() { std::cout << "otherWay\n"; }
public:
void doingSomething() {
complexMethod([this]() { return myWay(); });
}
void doingAnotherThing() {
complexMethod([this]() { return otherWay(); });
}
};
int main() {
B b{};
b.doingSomething();
b.doingAnotherThing();
}
// Outputs:
//
// myWay
// otherWay
Is there any implementation technique (one of the above or some other) were I would be able to make
variableMethod
return type and parameters explicit? How would I do it?
您可以使用 const std::function<bool(int,double)>& f
作为接收 complexMethod
函数的参数。并且仍然传递一个 lambda。请注意,尽管 lambda 表达式现在正在接收 (int i, double d)
(也可能是 (auto i, auto d)
)。
#include <functional> // function
#include <ios> // boolalpha
#include <iostream> // cout
class A {
protected:
bool complexMethod(const std::function<bool(int,double)>& f, int i, double d)
{ return f(i, d); }
};
class B : public A {
bool myWay(int a, double b) { return a < static_cast<int>(b); }
bool otherWay(int a, double b) { return a*a < static_cast<int>(b); }
public:
bool doingSomething(int a, double b) {
return complexMethod([this](int i, double d) {
return myWay(i, d); }, a, b);
}
bool doingAnotherThing(int a, double b) {
return complexMethod([this](auto i, auto d) {
return otherWay(i, d); }, a, b);
}
};
int main() {
B b{};
std::cout << std::boolalpha << b.doingSomething(3, 5.5) << "\n";
std::cout << std::boolalpha << b.doingAnotherThing(3, 5.5) << "\n";
}
// Outputs:
//
// true
// false
请注意,同样可以使用模板完成,尽管您不会使签名显式。
#include <functional> // function
#include <ios> // boolalpha
#include <iostream> // cout
class A {
protected:
template <typename F, typename... Args>
auto complexMethod(F&& f, Args&&... args) -> decltype(f(args...))
{ return f(args...); }
};
class B : public A {
bool myWay(int a, double b) { return a < static_cast<int>(b); }
bool otherWay(int a, double b) { return a*a < static_cast<int>(b); }
public:
bool doingSomething(int a, double b) {
return complexMethod([this](auto i, auto d) {
return myWay(i, d); }, a, b);
}
bool doingAnotherThing(int a, double b) {
return complexMethod([this](auto i, auto d) {
return otherWay(i, d); }, a, b);
}
};
int main() {
B b{};
std::cout << std::boolalpha << b.doingSomething(3, 5.5) << "\n";
std::cout << std::boolalpha << b.doingAnotherThing(3, 5.5) << "\n";
}
// Outputs:
//
// true
// false
Which technique is recommended? Why (speed, flexibility, readility...)?
Scott Meyer 的 Effective Modern C++ 一书的第 34 项标题为 Prefer lambdas to std::bind
。它以一句话总结结束:Lambdas are more readable, more expressive, and may be more efficient than using std::bind
。但是,它也提到了 std::bind
可能比 lambda 有用的情况。