c++ - 可变参数和函数指针 vector

标签 c++ c++11 templates variadic-templates variadic-functions

我在使用 C++11 时遇到了一个几乎合乎逻辑的问题。

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

一切顺利,直到我希望对要绘制的值应用单一条件。假设我有一个 FooPlotter 类,它有类似的内容:

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

这将遍历我的数据容器并将条件 Foo::*Bar 应用于所有元素,绘制满足给定条件的值。

到目前为止一切顺利。

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

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

    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 对象?


编辑:关于我想要获得的结果的附加信息。

首先,我希望能够创建 FooCondition 项的 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 结构 应该使用重载运算符自动将正确的参数传递给方法。

这里的问题是找到正确的容器来创建 FooCondition 模板的集合,而不管它们的参数包的大小。

最佳答案

在我看来,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(); });

关于c++ - 可变参数和函数指针 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49261281/

相关文章:

c++ - 尝试构建任意深度树状结构的可变模板实例化中的无限递归

c++ - GCC 4.7.2:带有指向成员函数指针的 std::thread

javascript - 以 HTML 形式显示 Gmail API JSON 输出的模板?

c++ - 什么是单元测试模板化 C++ 方法/类/函数的好方法?

c++ - const 限定符和数组

c++ - 检查 struct 的成员是否仅按字母顺序排列

c++ - 一个 vector/映射中的 std::function 变量参数

c++ - 未声明 rapidjson 的 _snprintf?

c++ - 有没有办法让类成员对象的模板调用不同的构造函数?

C++ OO设计: Inheritance of template parameter