std:: accumulate division by zero

Viewed 98

I do not understand why I get a division by zero in the following code.

template <typename T>
typename std::iterator_traits<T>::value_type avg_abs_difference(T first, T second)
{
    using Type = typename std::iterator_traits<T>::value_type;
    if(first == second)return 0;
    Type oldValue = *first;
    Type count = 0;
    Type res = std::accumulate(std::next(first), second, 0, [&](Type a, Type b)
                           {
                            Type result = a + std::abs(b- oldValue);
                            oldValue = b;
                            ++count;
                            return  result; }
                            )/ count;
    return res ;
}

but when I pull the division outward like this, it does not occur.

template <typename T>
typename std::iterator_traits<T>::value_type avg_abs_difference(T first, T second)
{
    using Type = typename std::iterator_traits<T>::value_type;
    if(first == second)return 0;
    Type oldValue = *first;
    Type count = 0;
    Type res = std::accumulate(std::next(first), second, 0, [&](Type a, Type b)
                           {
                            Type result = a + std::abs(b- oldValue);
                            oldValue = b;
                            ++count;
                            return  result; }
                            );
    return res / count;
}
1 Answers

That's because "count" is evaluated before std::accumulate, so the side effect is not taken into consideration.

https://en.cppreference.com/w/cpp/language/eval_order

Order of evaluation of any part of any expression, including order of evaluation of function arguments is unspecified (with some exceptions listed below). The compiler can evaluate operands and other subexpressions in any order, and may choose another order when the same expression is evaluated again.

Related