As a part of a much larger project, one of my objects (Thing in MWE) has a set of filters (filterStrong, filterWeak) defined on it. These filters are used in a complexFilteringProcedure, allowing for choice of filtering rule, where decisions depend on the success of the chosen filtering operation.
I implemented this by holding a vector of all possible filters in filteringOptions and implementing a single public filtering interface, filterUsingRule. Ideally, this would allow me to later on add new filtering rules to the project as I need them, and only modify the setFilteringFunction where the filter list is initialized.
Now, I started writing a new set of filtering rules, and realized all of them could be obtained by decorating the current filtering rules all in the same manner (softenFilter; please do correct me if "decorating" is the wrong expression here). In the actual implementations, all of these methods require access to private members of the Thing. I remembered reading into std::bind recently and taught, great.
Reading up a little bit more on std::bind, I think the possible reasons for my problems are twofold:
- the return type of
std::bindis a templated mess, and definitely notThing::filteringFunction - I might be binding the
thisreferring to the calling object when definingsoftStrongandsoftWeak
But, I am stuck further than that, not sure how to look for a solution to my specific problem. My main question are: Can this functionality be achieved? (functionality of filterUsingRule) and further, Can this functionality be achieved elegantly? (I know I could always define a set of functions bool softStrong(int param) { return softenFilter(filterStrong, param); } that manually bind the filters to the decorator, but I was hoping that std::bind or some new C++ magic would help with that).
The MWE recreating what I have successfully done and what I would like to achieve is as follows:
#include <iostream>
#include <vector>
#include <functional>
class Thing{
private:
typedef bool (Thing::*filteringFunction)(int);
static std::vector<filteringFunction> filteringOptions;
bool filterStrong(int parameter) {return parameter > 10;}
bool filterWeak(int parameter) {return parameter > 5;}
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); // not ok
//filteringOptions.emplace_back(softWeak); // not ok
}
public:
Thing(){
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
std::cout << "Filtering: " << aThing.filterUsingRule(parameter, rule);
std::cout << std::endl;
// and some more things
}
int main(void){
Thing myThing;
complexFilteringProcedure(myThing, 7, 0); // uses strong rule
complexFilteringProcedure(myThing, 7, 1); // uses weak rule
//complexFilteringProcedure(myThing, 7, 2); // how to use soft strong rule?
//complexFilteringProcedure(myThing, 7, 3); // how to use soft weak rule?
}
Aucun commentaire:
Enregistrer un commentaire