C++ C++;绑定重载成员函数并作为参数传递
我有一个类,它有两个函数,可以启动和停止一组东西。由于这两个函数是相同的,除了它们最终分别对每件事情调用start或stop函数外,我想重构代码,以便将代码主体移动到通用函数,我的start和stop集合调用这个传递一个额外的参数,这是它们必须调用以启动或停止的函数 当然,在线上有很多C++ C++;绑定重载成员函数并作为参数传递,c++,std-function,stdbind,C++,Std Function,Stdbind,我有一个类,它有两个函数,可以启动和停止一组东西。由于这两个函数是相同的,除了它们最终分别对每件事情调用start或stop函数外,我想重构代码,以便将代码主体移动到通用函数,我的start和stop集合调用这个传递一个额外的参数,这是它们必须调用以启动或停止的函数 当然,在线上有很多std::bind()教程和示例,但我没有发现任何文章或问题/答案涵盖我面临的以下所有具体约束: 被约束的函数是使事情复杂化的成员;它也是非常量的 被绑定的函数也被重载,因此必须正确区分 大多数std::bind
std::bind()
教程和示例,但我没有发现任何文章或问题/答案涵盖我面临的以下所有具体约束:
- 被约束的函数是使事情复杂化的成员;它也是非常量的
- 被绑定的函数也被重载,因此必须正确区分
- 大多数
示例都使用std::bind()
,但在这种情况下,我需要知道auto
返回的类型,以便将其作为参数传递给std::bind()
action\u widgets()
- 有两个布尔值,
&a
,它们实际上是常量,可以绑定到函数中,尽管我在这里还没有这样做。一次只做一件事b
#include <string>
#include <vector>
#include <functional>
struct Processor {
using WidgetActionFunction = bool(Processor::*)(const std::string&,
bool, bool);
// Function wrapper
using WidgetActionWrapper = std::function<bool(Processor&,
const std::string&, bool, bool)>;
// These functions in reality are tied heavily to the class and are quite
// large. They cannot easily be made static or free.
bool stop_widget(const std::string& key, bool a, bool b) { return true; }
bool start_widget(const std::string& key, bool a, bool b) { return true; }
// Just to make life difficult, there are some overloads, which we're not
// interested in.
bool stop_widget(int event, bool a, bool b) { return true; }
bool start_widget(int event, bool a, bool b) { return true; }
// I created this function because start_widgets() and stop_widgets() were
// identical except that internally they call start_widget() and stop_widget()
// respectively. I want the main body of the code to be here and for the
// appropriate function to be passed in.
void action_widgets(std::vector<std::string>& widgets,
bool a, bool b, WidgetActionWrapper& func) {
std::vector<std::string> valid_widgets;
valid_widgets.reserve(widgets.size());
for (const auto& widget : widgets) {
if (func(*this, widget, a, b)) { // This is where func() gets invoked.
valid_widgets.push_back(widget);
}
}
std::swap(widgets, valid_widgets);
}
void start_widgets(std::vector<std::string>& widgets, bool a, bool b) {
WidgetActionWrapper func =
std::bind(static_cast<WidgetActionFunction>(&Processor::start_widget),
this, std::placeholders::_1, a, b); // compilation fails here.
action_widgets(widgets, a, b, func);
}
void stop_widgets(std::vector<std::string>& widgets, bool a, bool b) {
// Very similar to start_widgets() but calls with bound stop_widget()
// instead.
}
};
int main()
{
return 0;
}
#包括
#包括
#包括
结构处理器{
使用WidgetActionFunction=bool(处理器::*)(常量std::string&,
bool,bool);
//函数包装器
使用WidgetActionWrapper=std::函数;
//实际上,这些函数与类紧密相关,并且非常复杂
//大的。它们不容易固定或自由。
bool stop_小部件(const std::string&key,bool a,bool b){return true;}
bool start_小部件(const std::string&key,bool a,bool b){return true;}
//只是为了让生活变得困难,有一些超载,而我们不是
//对……感兴趣。
bool stop_小部件(int事件,bool a,bool b){return true;}
bool start_小部件(int事件,bool a,bool b){return true;}
//我创建这个函数是因为start\u widgets()和stop\u widgets()是
//除了在内部调用start_widget()和stop_widget()之外,其他都是相同的
//分别。我希望代码的主体在这里和
//要传入的适当函数。
void action_小部件(标准::向量和小部件,
布尔a、布尔b、WidgetActionWrapper和func){
std::vector-valid\u小部件;
有效的_widgets.reserve(widgets.size());
用于(常量自动和小部件:小部件){
如果(func(*this,widget,a,b)){//这是调用func()的地方。
有效的小部件。推回(小部件);
}
}
std::swap(小部件、有效的_小部件);
}
void start_小部件(std::vector&widgets、bool a、bool b){
WidgetActionWrapper函数=
std::bind(静态\u转换(&处理器::启动\u小部件),
这个,std::占位符::_1,a,b);//这里编译失败。
action_小部件(小部件、a、b、func);
}
void stop_小部件(std::vector&widgets、bool a、bool b){
//非常类似于start_widgets(),但使用绑定的stop_widget()调用
//相反。
}
};
int main()
{
返回0;
}
编译时,我得到以下错误:
error: conversion from ‘std::_Bind_helper<false, bool (Processor::*)(const std::basic_string<char>&, bool, bool), Processor* const, const std::_Placeholder<1>&, bool&, bool&>::type {aka std::_Bind<std::_Mem_fn<bool (Processor::*)(const std::basic_string<char>&, bool, bool)>(Processor*, std::_Placeholder<1>, bool, bool)>}’ to non-scalar type ‘Processor::WidgetActionFunctor {aka std::function<bool(Processor&, const std::basic_string<char>&, bool, bool)>}’ requested
错误:请求从'std::_Bind_helper::type{aka std::_Bind}'转换为非标量类型'Processor::WidgetActionFunctor{aka std::function}'
显然,我的函数包装器别名与std::bind()
返回的内容不匹配,但我哪里出错了
最后一点警告:因为这是针对公司客户的,所以我只能使用C++11解决方案(尽管为其他人的利益提供的解决方案受到赞赏),而且,尽管我热衷于使用lambdas的更简单的解决方案,但我的同事认为,从技术角度来看,这可能同样棘手,我很想知道我错了什么。您可以将
std::bind
看作是在分配给std::函数时去掉了前几个参数
例如,这:
bool(Processor::*)(const std::string&, bool, bool);
// Which is this:
class Processor { bool f(const std::string&, bool, bool); }
decltype(&Processor::f)
分配给std::函数
当您将它绑定到一个处理器&
(在您的例子中,*this
,就像std::bind(&Processor::f,*this)
),它现在应该被分配到std::函数
(因为bind
摆脱了处理器&
参数)
这里有两个修正。不要绑定:
WidgetActionWrapper func =
std::bind(static_cast<WidgetActionFunction>(&Processor::start_widget),
*this, std::placeholders::_1, a, b); // compilation fails here.
// becomes
WidgetActionWrapper func = &Processor::start_widget;
我认为这里不需要lambda或std::bind
,尤其不需要std::function
,以及它将引入的所有开销。您可以简单地使用一个成员函数模板,该模板被赋予一个指向实际成员函数的指针,以调用每个小部件作为模板参数,例如:
struct Processor
{
bool stop_widget(const std::string& key, bool a, bool b) { return true; }
bool start_widget(const std::string& key, bool a, bool b) { return true; }
bool stop_widget(int event, bool a, bool b) { return true; }
bool start_widget(int event, bool a, bool b) { return true; }
template <bool (Processor::* func)(const std::string&, bool, bool)>
void action_widgets(std::vector<std::string>& widgets, bool a, bool b)
{
std::vector<std::string> valid_widgets;
valid_widgets.reserve(widgets.size());
for (const auto& widget : widgets)
{
if ((this->*func)(widget, a, b))
{
valid_widgets.push_back(widget);
}
}
std::swap(widgets, valid_widgets);
}
};
struct处理器
{
bool stop_小部件(const std::string&key,bool a,bool b){return true;}
bool start_小部件(const std::string&key,bool a,bool b){return true;}
bool stop_小部件(int事件,bool a,bool b){return true;}
bool start_小部件(int事件,bool a,bool b){return true;}
模板
void action_小部件(std::vector&widgets、bool a、bool b)
{
std::vector-valid\u小部件;
有效的_widgets.reserve(widgets.size());
用于(常量自动和小部件:小部件)
{
如果((此->*func)(小部件,a,b))
{
有效的小部件。推回(小部件);
}
}
std::swap(小部件、有效的_小部件);
}
};
然后
processor.action_widgets<&Processor::start_widget>(widgets, true, false);
processor.action_widgets<&Processor::stop_widget>(widgets, true, false);
processor.action\u小部件(小部件,真、假);
processor.action_小部件(小部件,true、false);
这基本上只会导致编译器为您生成原始的start\u小部件
和stop\u小部件
函数,就像您
processor.action_widgets<&Processor::start_widget>(widgets, true, false);
processor.action_widgets<&Processor::stop_widget>(widgets, true, false);