3

ブーストアキュムレータを使用してローリング平均を計算しようとしています。次のように変数をインラインで宣言すると:

#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.
4

1 に答える 1

8

この問題の正しい解決策は次のとおりです。

#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
于 2013-03-06T01:02:47.787 に答える