Могут ли аккумуляторы повышенного уровня использоваться в качестве членов класса

Я пытаюсь использовать повышающий аккумулятор для вычисления скользящего среднего. Когда я объявляю переменную inline следующим образом:

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

2

Решение

Правильное решение этой проблемы заключается в следующем:

#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
8

Другие решения

Других решений пока нет …