2

I am attempting to interpret one of the answers to the question "calculate mean and standard deviation from a vector of samples in C++ using boost" found at Calculate mean and standard deviation from a vector of samples in C++ using Boost.

The question is about how to calculate mean and standard deviation for a vector containing samples using boost. The answer given by David Nehme is as follows.


Using accumulators is the way to compute means and standard deviations in boost.

accumulator_set<double, stats<tag::variance> > acc;
for_each(a_vec.begin(), a_vec.end(), bind<void>(ref(acc), _1));

cout << mean(acc) << endl;
cout << sqrt(variance(acc)) << endl;

Can someone explain this answer? It looks a bit like a magical incantation to me.

I do not know what "bind(ref(acc), _1)" means. From reading the Boost bind documentation found at www.boost.org/doc/libs/1_55_0/libs/bind/bind.html, I can assume that bind refers to boost::bind, ref refers to boost::ref, and _1 refers to the _1 placeholder object defined in boost\bind\placeholders.hpp.

However, I do not know how all that fits together. The documentation on boost::bind is a little vague. It talks about using boost::bind with functions but acc is a variable.

What exactly does the for_each line do?

Community
  • 1
  • 1
Benilda Key
  • 2,836
  • 1
  • 22
  • 34

1 Answers1

1

I'm assuming that you understand what an iterator is; for_each takes a starting iterator, an ending iterator, and a function on which to call on the objects associated with the iterator. std::for_each

  1. bind<void>(ref(acc),_1) is functor (or function object - think of this like a function with internal state) that takes one double and returns nothing - roughly equivalent to void function(double));
  2. ref(acc) allows you to minimize the penalty for copying an object; ref
  3. acc in this case is an accumulator has the following function within its definition operator()(double value);
  4. _1 is known as a place holder (a little complex, but see placeholders) - roughly speaking placeholder acts a mechanism to pass a double into the functor.
kingtorus
  • 953
  • 12
  • 15
  • I see what I was missing. I did not realize the significance of the following operator while I was reading the documentation earlier. void operator ()(Args const & args) This is what makes acc a function object and not a simple set or vector. Now the magical incantation makes sense! – Benilda Key Feb 12 '14 at 07:39
  • @BenKey acc is already a function object, designed specifically to be passed to (and returned from) std::for_each as-is. – Cubbi Feb 12 '14 at 12:21
  • @kingtorus Note that `ref` does more than just optimize: the semantics are difference, since the functor isn't copied even if the bind-expression is – sehe Feb 12 '14 at 13:36
  • Just to clarify, he probably is using C++11 [since he is using placeholders (although - boost::functional provides something similar)] - `for_each` should then use move semantics - but will possibly have to copy the functor during the first call. The semantics of the `for_each` is the same (*important*); on the other hand the internal workings of the functor have been optimized (as pointed out by @sehe). – kingtorus Feb 12 '14 at 23:09
  • 1
    The semantics for `ref(F)` vs. `F` are **not** the same /in general/. So the phrase `ref(acc) allows you to minimize the penalty for copying an object` seems a tad misleading to me. – sehe Feb 12 '14 at 23:44
  • I guess I wasn't that clear, `bind(...)` is the functor. The advantage of the ref is that the internal state (the accumulator) is no longer copied. The entire point of passing an accumulator by reference is spelled out [here](http://www.boost.org/doc/libs/1_55_0/doc/html/accumulators/user_s_guide.html) - 'but some accumulators are not cheap to copy.' I guess I glossed over the difference between value and reference semantics because I feel that it is irrelevant towards answering the question. – kingtorus Feb 13 '14 at 00:01
  • so is there a way to do it without `boost::bind` but using c++11/14 features, such as, lambda, bind, or move semantics? – kirill_igum Dec 22 '14 at 22:18