首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >保存成员函数指针和修饰成员函数指针的集合。

保存成员函数指针和修饰成员函数指针的集合。
EN

Stack Overflow用户
提问于 2018-04-05 16:25:56
回答 3查看 168关注 0票数 0

作为一个大得多的项目的一部分,my对象之一(MWE中的Thing)在其上定义了一组过滤器(filterStrongfilterWeak)。目标是使用complexFilteringProcedure**,中所有已实现的过滤器,其中用户可以通过参数选择筛选规则,而函数本身将取决于所选筛选规则的成功与否。**函数complexFilteringProcedure将对一个Thing类型的对象进行操作,并根据参数调用其私有方法之一(筛选规则)。

我通过在vector中保存所有可能的过滤器并实现一个公共过滤接口filterUsingRule来实现这一点。理想情况下,这将允许我稍后在需要时向项目添加新的筛选规则,并且只修改初始化筛选列表的setFilteringFunction

现在,我开始编写一组新的过滤规则,并意识到所有这些规则都可以通过以相同的方式修饰当前的过滤规则来获得(softenFilter;如果这里的“修饰”是错误的表达式,请纠正我)。我记得最近读了std::bind的书,教过,太棒了。我还想在我的filteringOptions,列表中添加的所有修饰过滤规则,也就是用softenFilter修饰的每个原始过滤器。

std::bind上读更多的文章,我认为造成问题的可能原因有两方面:

  • 返回类型的std::bind是一个模板化的混乱,绝对不是Thing::filteringFunction
  • 在定义thissoftWeak时,我可能会绑定引用调用对象的softWeak

但是,我被困在更远的地方,不知道如何找到解决我的具体问题的办法。我的主要问题是:能实现这个功能吗?(filterUsingRule的功能),而且,能优雅地实现这个功能吗?(我知道我总是可以定义一组函数bool softStrong(int param) { return softenFilter(filterStrong, param); },它可以手动地将过滤器绑定到装饰器,但我希望std::bind或一些新的C++魔术能够在这方面有所帮助)。

MWE重新创建了我已经成功完成的工作和我想要实现的目标如下:

代码语言:javascript
复制
#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?
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-04-05 17:07:47

您可以使用std::function

代码语言:javascript
复制
using filteringFunction = std::function<bool (Thing&, int)>;

然后

代码语言:javascript
复制
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) });
}
票数 3
EN

Stack Overflow用户

发布于 2018-04-05 16:33:04

您必须使用std::function的专门化作为向量元素类型。关键问题是std::bind()返回的对象不是裸函数指针。它实际上是一个可赎回 --一个函数对象--它是某种类型(确切地说,什么类型是不重要的事实上,没有具体说明),它有一个具有适当返回类型的operator(),它接受适当的参数。这正是std::function的作用--一种可以包装任何可调用的正确签名的类型,它允许您使用已知的具体类型来处理它,而不管可调用的实际类型是什么。

代码语言:javascript
复制
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的代码,修改后使用了这种技术。

代码语言:javascript
复制
#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?
}
票数 0
EN

Stack Overflow用户

发布于 2018-04-11 10:33:05

代码语言:javascript
复制
typedef std::function<bool(Thing*, int)> filteringFuction;

现在,您可以使用静态函数以及std::bind和lambda,或者任何接受int并返回bool的可调用函数。

代码语言:javascript
复制
    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);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49677200

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档