作为一个大得多的项目的一部分,my对象之一(MWE中的Thing)在其上定义了一组过滤器(filterStrong,filterWeak)。目标是使用complexFilteringProcedure**,中所有已实现的过滤器,其中用户可以通过参数选择筛选规则,而函数本身将取决于所选筛选规则的成功与否。**函数complexFilteringProcedure将对一个Thing类型的对象进行操作,并根据参数调用其私有方法之一(筛选规则)。
我通过在vector中保存所有可能的过滤器并实现一个公共过滤接口filterUsingRule来实现这一点。理想情况下,这将允许我稍后在需要时向项目添加新的筛选规则,并且只修改初始化筛选列表的setFilteringFunction。
现在,我开始编写一组新的过滤规则,并意识到所有这些规则都可以通过以相同的方式修饰当前的过滤规则来获得(softenFilter;如果这里的“修饰”是错误的表达式,请纠正我)。我记得最近读了std::bind的书,教过,太棒了。我还想在我的filteringOptions,列表中添加的所有修饰过滤规则,也就是用softenFilter修饰的每个原始过滤器。
在std::bind上读更多的文章,我认为造成问题的可能原因有两方面:
std::bind是一个模板化的混乱,绝对不是Thing::filteringFunction。this和softWeak时,我可能会绑定引用调用对象的softWeak但是,我被困在更远的地方,不知道如何找到解决我的具体问题的办法。我的主要问题是:能实现这个功能吗?(filterUsingRule的功能),而且,能优雅地实现这个功能吗?(我知道我总是可以定义一组函数bool softStrong(int param) { return softenFilter(filterStrong, param); },它可以手动地将过滤器绑定到装饰器,但我希望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?
}发布于 2018-04-05 17:07:47
您可以使用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) });
}发布于 2018-04-05 16:33:04
您必须使用std::function的专门化作为向量元素类型。关键问题是std::bind()返回的对象不是裸函数指针。它实际上是一个可赎回 --一个函数对象--它是某种类型(确切地说,什么类型是不重要的事实上,没有具体说明),它有一个具有适当返回类型的operator(),它接受适当的参数。这正是std::function的作用--一种可以包装任何可调用的正确签名的类型,它允许您使用已知的具体类型来处理它,而不管可调用的实际类型是什么。
typedef std::function<bool(int)> filteringFunction;
static std::vector<filteringFunction> filteringOptions;
// now can you store your member function pointers in
// filteringOptions after bind()ing the first parameter
// as you've already done为了让怀疑论者满意,下面是OP的代码,修改后使用了这种技术。
#include <iostream>
#include <vector>
#include <functional>
class Thing{
private:
int basicFilter;
typedef std::function<bool(int)> filteringFunction;
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 (!f(parameter))
return f(parameter + 2);
return true;
}
void setFilteringFunctions(void){
filteringFunction strong = std::bind(&Thing::filterStrong,
this, std::placeholders::_1);
filteringFunction weak = std::bind(&Thing::filterWeak,
this, std::placeholders::_1);
filteringFunction softStrong = std::bind(&Thing::softenFilter,
this, strong, std::placeholders::_1);
filteringFunction softWeak = std::bind(&Thing::softenFilter,
this, weak, std::placeholders::_1);
filteringOptions.emplace_back(softStrong);
filteringOptions.emplace_back(softWeak);
}
public:
Thing(int basicFilter) : basicFilter(basicFilter){
if (Thing::filteringOptions.empty())
setFilteringFunctions();
}
bool filterUsingRule(int parameter, int rule = 0){
return ((int)Thing::filteringOptions.size() > rule) &&
filteringOptions[rule](parameter);
}
};
std::vector <Thing::filteringFunction> Thing::filteringOptions(0);
void complexFilteringProcedure(Thing &aThing, int parameter, int rule){
// do a lot of things
std::cout << "Filtering: " << aThing.filterUsingRule(parameter, rule) << 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 use soft strong rule?
//complexFilteringProcedure(otherThing, 7, 3); // how to use soft weak rule?
}发布于 2018-04-11 10:33:05
typedef std::function<bool(Thing*, int)> filteringFuction;现在,您可以使用静态函数以及std::bind和lambda,或者任何接受int并返回bool的可调用函数。
static bool test(Thing*, int);
static bool decoratee(Thing*, bool , int);
this->filteringOptions.emplace_back([](Thing* sth, int x){return false;});
this->filteringOptions.emplace_back(&Thing::weakFilter);
this->filteringOptions.emplace_back(std::bind(decoratee, _1, false, _2));
this->filteringOptions.emplace_back(&test);
int param;
for(auto& callee:this->filteringOptions)
callee(this,param);https://stackoverflow.com/questions/49677200
复制相似问题