|
Boost Users : |
Subject: Re: [Boost-users] Troubles using boost::circular_buffer
From: Ted Byers (r.ted.byers_at_[hidden])
Date: 2012-04-17 09:59:28
Thanks Daryle, I'll look into that..
Cheers
Ted
From: boost-users-bounces_at_[hidden]
[mailto:boost-users-bounces_at_[hidden]] On Behalf Of Daryle Walker
Sent: April-17-12 5:10 AM
To: Boost Users
Subject: Re: [Boost-users] Troubles using boost::circular_buffer
From: r.ted.byers_at_[hidden]
Date: Thu, 12 Apr 2012 23:54:41 -0400
In the header that provides the prototypes for the functions in this
particular CPP file, I have:
double calculateStdDev(const boost::circular_buffer<double>& input, double&
mean, double& variance, double& stddev);
And gcc v 4.3.4 gives me the following error:
../../include/distribution.moments.hpp:9: error: wrong number of template
arguments (1, should be 2)
/usr/local/include/boost/circular_buffer/base.hpp:70: error: provided for
'template<class T, class Alloc> class boost::circular_buffer'
I am not sure I understand why.
The circular_buffer class template does take two arguments, but the
forwarding header supplies a default argument to the second one
(std::allocator<T>). Somehow that forward declaration is being missed.
Does this mean that I have to make calculateStdDev a template function?
E.g.:
template <typename T>
double calculateStdDev(const boost::circular_buffer<double, T>& input,
double& mean, double& variance, double& stddev) {
// and put the entire implementation here in the header
instead of in the cpp file with the overloads for other types such as
std::vector)
}
No, your code computation code isn't the problem.
But, if that is the case, why is it possible to instantiate such a buffer
using the following (as in the example)?
boost::circular_buffer<int> cb(3);
I must have missed something, but I don't know what.
Yeah, that part of your code is seeing the defaulted argument.
I looked up standard-deviation in Wikipedia, and I think you should compute
your data in a different way:
// Not tested
class mean_and_stddev_computer
{
double m_, q_;
unsigned long c_;
public:
typedef double argument_type, result_type;
mean_and_stddev_computer()
: m_(), q_(), c_()
{}
void operator ()( double sample )
{
double const delta = sample - m_;
m_ += delta / ++c_;
q_ += delta * ( sample - m_ );
}
double sample_variance() const { return (c_ > 1u) ? (q_ / (c_ - 1)) :
0; }
double standard_variance() const { return c ? (q_ / c_) : 0; }
double sample_stddev() const { return std::sqrt(sample_variance()); }
double standard_stddev() const { return
std::sqrt(standard_variance()); }
double mean() const { return m_; }
unsigned long count() const { return c_; }
double variance() const {return sample_variance(); }
double stddev() const { return sample_stddev(); }
double operator ()() const { return stddev(); }
};
Then your code would use this function object with std::for_each. It should
work with anything that makes iterators, not just circular_buffer. If
you're going to take the average from several buffers, make sure to get your
function object to assigned the value of the return value of for_each, so
the averaging data is carried over.
Daryle W.
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net