如何正确设计从结构中获取不同字段的函子

How to properly design a functor that would fetch different fields from a struct

本文关键字:字段 获取 何正确 结构      更新时间:2023-10-16

我有一个由struct组成的std::vector,其中包含几个字段,如下所示:

struct stats
{
   double mean;
   double median;
   double rms;
};
std::vector<stats> data;

我想设计一个对vector进行操作的函数,例如,构建一个直方图。我希望能够指定这个函数应该在struct的哪个字段上运行。例如:

build_histogram(data, get_mean);
build_histogram(data, get_median);
build_histogram(data, get_rms);

我尝试在stats类中实现一些getter,比如:

struct stats
{
   double mean;
   double median;
   double rms;
   struct get_mean { double operator() () { return mean; };
   struct get_median { double operator() () { return median; };
   struct get_rms { double operator() () { return rms; };
};

但它表示,这是对非静态成员meanmedianrms的无效使用。我如何才能正确地实现它?

您试图传递一个类型,而不是一个对象。在容器上迭代时,函子应接受向量元素作为参数。有几种方法可以做到这一点,其中最类似于你试图做的是:

struct stats
{
   double mean;
   double median;
   double rms;
   struct get_mean { double operator() (const stats& s) { return s.mean; } };
   struct get_median { double operator() (const stats& s) { return s.median; } };
   struct get_rms { double operator() (const stats& s) { return s.rms; } };
};
build_histogram(data, stats::get_mean());
build_histogram(data, stats::get_median());
build_histogram(data, stats::get_rms());

但是,如果您支持Lambda(C++11中的新功能),那么使用它们会更简单。

struct stats
{
   double mean;
   double median;
   double rms;
};
build_histogram(data, [](const stats& s) { return s.mean; });
// etc.

为了使其中任何一个工作,build_histogram应该是一个函数模板,第二个参数是任何可调用对象(根据需要更改ReturnType)。

template <typename F>
ReturnType build_histogram(const std::vector<stats>& data, F functor)
{
     // here you can use functor() or pass it to STL algorithm (e.g. find_if)
}

定义函子的不同方法是(或多或少按照我的偏好顺序)

  • lambda函数(C++11)
  • 自由函数
  • functor对象(这就是您所做的,但它不必嵌套在类型中)
  • 静态成员函数
  • 使用std::bind的成员函数(我不建议这样做)

为什么要重新发明元组?

enum {mean, median, rms};
typedef std::tuple<double,double,double>  stats;
stats   st{1,2,3};
cout << get<mean>(st);