代码之家  ›  专栏  ›  技术社区  ›  jetstream

变量参数和函数指针向量

  •  2
  • jetstream  · 技术社区  · 7 年前

    在使用C++11时,我面临着一个几乎合乎逻辑的问题。

    我有一个必须绘制的类(又名绘制趋势),我想排除所有不满足给定条件的点。 分数属于同一级别 Foo 所有的条件函数都是用签名定义的 bool Foo::Bar(Args...) const 哪里 Args... 表示多个参数(例如返回值的上限和下限)。

    直到我希望对要绘制的值应用一个条件时,一切都进展顺利。假设我有一个 FooPlotter 类,该类具有以下内容:

    template<class ...Args> GraphClass FooPlotter::Plot([...],bool (Foo::*Bar)(Args...), Args... args)
    

    它将遍历我的数据容器并应用条件 Foo::*Bar 绘制满足给定条件的值。

    到目前为止还不错。

    在给定的点上,我想将条件向量传递给同一个方法,以便使用多个条件来过滤数据。

    我首先创建了一个类来包含以后需要的所有内容:

        template<class ...Args> class FooCondition{
            public:
                FooCondition(bool (Foo::*Bar)(Args...) const, Args... args)
                {
                    fCondition = Bar;
                    fArgs = std::make_tuple(args);
                }
                bool operator()(Foo data){ return (data.*fCondition)(args); }
            private:
                bool (Foo::*fCondition)(Args...) const;
                std::tuple<Args...> fArgs;
        };
    

    然后,我陷入了如何定义一个(iterable)容器的困境,该容器可以包含 FooCondition 对象,尽管它们的 参数。。。 参数包。 问题是有些方法 Args... = uint64_t,uint_64_t 而其他人则不需要调用任何参数。

    我深入研究了如何处理这种情况。我尝试了几种方法,但没有一种效果很好。

    目前,我在所有 Bar 方法,统一它们并围绕这个问题开展工作,但我并不真正满意!

    你们中的一些人对如何存储不同类型的 食品条件 优雅的物品?


    编辑:有关我想要获得的结果的其他信息。

    首先,我希望能够创建 std::vector 属于 食品条件 项目:

        std::vector<FooCondition> conditions;
        conditions.emplace_back(FooCondition(&Foo::IsBefore, uint64_t timestamp1));
        conditions.emplace_back(FooCondition(&Foo::IsAttributeBetween, double a, double b));
        conditions.emplace_back(FooCondition(&Foo::IsOk));
    

    在这一点上,我希望我可以在我的 FooPlotter::Plot 方法:

        GraphClass FooPlotter::Plot(vector<Foo> data, vector<FooCondition> conditions){
            GraphClass graph;
            for(const auto &itData : data){
                bool shouldPlot = true;
                for(const auto &itCondition : conditions){
                    shouldPlot &= itCondition(itData);
                }
                if(shouldPlot) graph.AddPoint(itData);
            }
            return graph;
        }
    

    正如你所说 FooCondition struct 应使用重载运算符自动将正确的参数传递给方法。

    这里的问题是找到能够创建 食品条件 模板,尽管它们的参数包很大。

    2 回复  |  直到 7 年前
        1
  •  1
  •   max66    7 年前

    在我看来 FooCondition 您正在尝试为 std::function<bool(Foo *)> (或者可能 std::function<bool(Foo const *)> )已初始化为 std::bind 修正了一些论点 Foo 方法。

    我是说。。。我认为

    std::vector<FooCondition> conditions;
    conditions.emplace_back(FooCondition(&Foo::IsBefore, uint64_t timestamp1));
    conditions.emplace_back(FooCondition(&Foo::IsAttributeBetween, double a, double b));
    conditions.emplace_back(FooCondition(&Foo::IsOk));
    

    你应该这样写

    std::vector<std::function<bool(Foo const *)>> vfc;
    
    using namespace std::placeholders;
    
    vfc.emplace_back(std::bind(&Foo::IsBefore, _1, 64U));
    vfc.emplace_back(std::bind(&Foo::IsAttributeBetween, _1, 10.0, 100.0));
    vfc.emplace_back(std::bind(&Foo::IsOk, _1));
    

    下面是一个简化的完整C++11示例,其中包含 main() 模拟 Plot()

    #include <vector>
    #include <iostream>
    #include <functional>
    
    struct Foo
     {
       double  value;
    
       bool IsBefore (std::uint64_t ts) const
        { std::cout << "- IsBefore(" << ts << ')' << std::endl; 
          return value < ts; }
    
       bool IsAttributeBetween (double a, double b) const
        { std::cout << "- IsAttrributeBetwen(" << a << ", " << b << ')'
             << std::endl; return (a < value) && (value < b); }
    
       bool IsOk () const
        { std::cout << "- IsOk" << std::endl; return value != 0.0; }
     };
    
    int main ()
     {
       std::vector<std::function<bool(Foo const *)>> vfc;
    
       using namespace std::placeholders;
    
       vfc.emplace_back(std::bind(&Foo::IsBefore, _1, 64U));
       vfc.emplace_back(std::bind(&Foo::IsAttributeBetween, _1, 10.0, 100.0));
       vfc.emplace_back(std::bind(&Foo::IsOk, _1));
    
       std::vector<Foo> vf { Foo{0.0}, Foo{10.0}, Foo{20.0}, Foo{80.0} };
    
       for ( auto const & f : vf )
        {
          bool  bval { true };
    
          for ( auto const & c : vfc )
             bval &= c(&f);
    
          std::cout << "---- for " << f.value << ": " << bval << std::endl;
        }
     }
    

    另一种方法是避免使用 std::绑定 并改用lambda函数。

    举例说明

    std::vector<std::function<bool(Foo const *)>> vfc;
    
    vfc.emplace_back([](Foo const * fp)
                     { return fp->IsBefore(64U); });
    vfc.emplace_back([](Foo const * fp)
                     { return fp->IsAttributeBetween(10.0, 100.0); });
    vfc.emplace_back([](Foo const * fp)
                     { return fp->IsOk(); });
    
        2
  •  0
  •   Jay    7 年前

    除了所有的foo-bar之外,您只需要一个具有方法的类,该方法可以实现以满足绘图要求。

    只需在接受节点的类上添加一个Plot方法,并在同一步骤中执行转换和打印。

    打印时不必担心参数,因为每个函数都知道它需要什么参数。

    因此,一个简单的参数*就足够了,如果为null,则没有参数,其中每个参数都显示其类型和值,或者可以从函数调用中假定。