Thanks Daryle, I'll look into that….

 

Cheers

 

Ted

 

From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] 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@gmail.com
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.