boost累加器可以用作类成员吗?

Can boost accumulators be used as class members

本文关键字:成员 累加器 boost      更新时间:2023-10-16

我试图使用boost累加器来计算滚动平均值。当我像这样声明内联变量时:

#include <iostream>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/rolling_mean.hpp>
using namespace boost::accumulators;
int main()
{
  // Define rolling_mean accumulator
  accumulator_set<double, stats<tag::rolling_mean > > acc(tag::rolling_window::window_size = 5);
    // push in some data ...
    acc(1.2);
    acc(2.3);
    acc(3.4);
    acc(4.5);
    // Display the results ...
    std::cout << "Mean:   " << rolling_mean(acc) << std::endl;
    return 0;
}

它工作得很好。当我像这样将累加器声明为类的成员时:

#include <iostream>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/rolling_mean.hpp>
using namespace boost::accumulators;
class DoMean {
private:
  accumulator_set<double, stats<tag::rolling_mean > > m_acc(tag::rolling_window::window_size = 5);
public:
  void addData(double val) {
    this->m_acc(val);
  }
  double getMean(void) {
    return rolling_mean(this->m_acc);
  }
};
int main()
{
  // Define an accumulator set for calculating the mean and the
  // 2nd moment ...
  DoMean meaner;
  meaner.addData(1.2);
  meaner.addData(2.3);
  meaner.addData(3.4);
  meaner.addData(4.5);
  // push in some data ...
  // Display the results ...
  std::cout << "Mean:   " << meaner.getMean() << std::endl;
  return 0;
}

失败,给编译器错误:

accumulators::tag::rolling_window::window_size is not a type
...blah blah, many type template errors etc.

这个问题的正确解决方案是:

#include <iostream>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/rolling_mean.hpp>
using namespace boost::accumulators;
class DoMean {
private:
  accumulator_set<double, stats<tag::rolling_mean > > m_acc;
public:
  DoMean(void): m_acc(tag::rolling_window::window_size = 5) {}
  void addData(double val) {
    this->m_acc(val);
  }
  double getMean(void) {
    return rolling_mean(this->m_acc);
  }
};
int main()
{
  // Define an accumulator set for calculating the mean and the
  // 2nd moment ...
  DoMean meaner;
  meaner.addData(1.2);
  meaner.addData(2.3);
  meaner.addData(3.4);
  meaner.addData(4.5);
  // push in some data ...
  // Display the results ...
  std::cout << "Mean:   " << meaner.getMean() << std::endl;
  return 0;
}

注意m_acc的初始化已经从声明的内联中移到了初始化列表中。这解决了所有编译器错误。实际上,如果我们考虑一下这里发生的事情,在类中使用累加器的初始尝试失败的原因是因为ISO c++禁止内联成员的初始化。

我们可以用另一个简单的类来演示:
#include <iostream>
class TestInit {
public:
  int m_init = 10;
};
int main() {
  TestInit inits;
  std::cout << "The value: " << inits.m_init << std::endl;
}

现在编译器给出了一个有用的信息:

/home/me/prog/cpp/acctest/testinit.cxx:5:16: error: ISO C++ forbids initialization of member m_init [-fpermissive]
/home/me/prog/cpp/acctest/testinit.cxx:5:16: error: making m_init static [-fpermissive]
/home/me/prog/cpp/acctest/testinit.cxx:5:16: error: ISO C++ forbids in-class initialization of non-const static member m_init