作为一个更大项目的一部分,我的一个对象(MWE 中的 Thing
)定义了一组过滤器(filterStrong
、filterWeak
)。 目标是使用 complexFilteringProcedure
中所有已实现的过滤器,用户可以通过参数选择过滤规则,函数本身将取决于选择的过滤规则是否成功。函数complexFilteringProcedure
将作用于 Thing
类型的对象,并根据参数调用其私有(private)方法之一(过滤规则)。
我通过持有 vector
来实现这一点filteringOptions
中所有可能的过滤器并实现一个公共(public)过滤接口(interface),filterUsingRule
.理想情况下,这将允许我稍后根据需要向项目添加新的过滤规则,并且只修改 setFilteringFunction
过滤器列表被初始化的地方。
现在,我开始编写一组新的过滤规则,并意识到所有这些都可以通过以相同的方式装饰当前的过滤规则来获得(softenFilter
;如果“装饰”是错误的,请纠正我此处表达)。我记得读过 std::bind
最近又受教了,太好了。 我还想在我的 filteringOptions
列表中添加所有修饰过滤规则,即每一个用softenFilter
修饰的原始过滤器.
阅读更多关于 std::bind
的内容,我认为我的问题可能有两个原因:
-
std::bind
的返回类型是一个模板化的困惑,绝对不是Thing::filteringFunction
- 我可能会绑定(bind)
this
在定义softStrong
时引用调用对象和softWeak
但是,我被困得更深了,不确定如何为我的特定问题寻找解决方案。我的主要问题是:可以实现这个功能吗?(filterUsingRule
的功能)并且可以优雅地实现这个功能吗?(我知道我总是可以定义一个一组函数 bool softStrong(int param) { return softenFilter(filterStrong, param); }
手动将过滤器绑定(bind)到装饰器,但我希望 std::bind
或一些新的 C++ 魔术会对此有所帮助。
MWE 重现了我已经成功完成的以及我想要实现的目标如下:
#include <iostream>
#include <vector>
#include <functional>
class Thing{
private:
int basicFilter;
typedef bool (Thing::*filteringFunction)(int);
static std::vector<filteringFunction> filteringOptions;
bool filterStrong(int parameter) {return parameter > basicFilter*2;}
bool filterWeak(int parameter) {return parameter > basicFilter;}
bool softenFilter(filteringFunction f, int parameter){
if (!((this->*(f))(parameter)))
return (this->*(f))(parameter+2);
return true;
}
void setFilteringFunctions(void){
Thing::filteringOptions.emplace_back(&Thing::filterStrong);
Thing::filteringOptions.emplace_back(&Thing::filterWeak);
auto softStrong = std::bind(&Thing::softenFilter,
&Thing::filterStrong,
std::placeholders::_1); // ok
auto softWeak = std::bind(&Thing::softenFilter,
&Thing::filterWeak,
std::placeholders::_1); // ok
filteringOptions.emplace_back(&softStrong); // how?
filteringOptions.emplace_back(softWeak); // how?
}
public:
Thing(int basicFilter) : basicFilter(basicFilter){
if (Thing::filteringOptions.empty())
setFilteringFunctions();
}
bool filterUsingRule(int parameter, int rule = 0){
return ((int)Thing::filteringOptions.size() > rule) &&
(this->*(Thing::filteringOptions[rule]))(parameter);
}
};
std::vector <Thing::filteringFunction> Thing::filteringOptions(0);
void complexFilteringProcedure(Thing &aThing, int parameter, int rule){
// do a lot of things
if (aThing.filterUsingRule(parameter, rule))
std::cout << "Filtering with " << rule << "successful" << std::endl;
else
std::cout << "Filtering with " << rule << "failed" << std::endl;
// and some more things
}
int main(void){
Thing myThing(5), otherThing(10);
complexFilteringProcedure(myThing, 7, 0); // uses strong rule
complexFilteringProcedure(otherThing, 7, 1); // uses weak rule
complexFilteringProcedure(myThing, 7, 2); // how to do this correctly?
complexFilteringProcedure(otherThing, 7, 3); // or this?
}
最佳答案
您可以使用 std::function
using filteringFunction = std::function<bool (Thing&, int)>;
然后
void setFilteringFunctions()
{
Thing::filteringOptions.emplace_back(&Thing::filterStrong);
Thing::filteringOptions.emplace_back(&Thing::filterWeak);
auto softStrong = std::bind(&Thing::softenFilter,
std::placeholders::_1,
&Thing::filterStrong,
std::placeholders::_2
);
auto softWeak = std::bind(&Thing::softenFilter,
std::placeholders::_1,
&Thing::filterWeak,
std::placeholders::_2);
Thing::filteringOptions.emplace_back(&softStrong);
Thing::filteringOptions.emplace_back(&softWeak);
// or
Thing::filteringOptions.emplace_back([](Thing& instance, int param){
return instance.filterStrong(param + 2) });
}
关于c++ - 持有成员函数指针和装饰成员函数指针的集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49677200/