可变参数和函数指针向量

射流

在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;
    };

然后,我陷入了如何定义一个(可迭代的)容器的问题,该容器可以包含FooCondition对象,尽管它们具有多种Args...参数包类型问题在于某些方法具有某些方法,Args... = uint64_t,uint_64_t而其他方法则不需要调用任何参数。

我对如何处理这种情况做了一些探讨。我尝试了几种方法,但是没有一种效果很好。

目前,我向所有Bar方法中添加了忽略的参数,将它们统一化并解决该问题,但是我并不十分满意!

你们中的一些人对如何以FooCondition一种优雅的方式存储不同类型的对象有想法吗?


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

首先,我希望能够创建一个std::vectorFooCondition项目:

    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应该使用重载运算符将正确的参数自动传递给方法。

这里的问题是找到正确的容器,以能够创建FooCondition模板集合,而不管其参数包的大小如何。

最高66

在我看来,随着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::bind和使用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(); });

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章