Conversion from _Ty to int warning in MSVC accumulate

Viewed 451

I cranked up MSVC warnings to level 4 and have a problem using accumulate over boost::circular_buffer. This code:

boost::circular_buffer<unsigned short> shorts;
shorts.resize(10);
unsigned short res = std::accumulate(shorts.begin(), shorts.end(), static_cast<unsigned short>(0));

Fail with a possible loss of data warning in the accumulate template (numeric):

// FUNCTION TEMPLATE accumulate
template<class _InIt,
    class _Ty,
    class _Fn>
    _NODISCARD inline _Ty accumulate(const _InIt _First, const _InIt _Last, _Ty _Val, _Fn _Reduce_op)
    {   // return noncommutative and nonassociative reduction of _Val and all in [_First, _Last), using _Reduce_op
    _Adl_verify_range(_First, _Last);
    auto _UFirst = _Get_unwrapped(_First);
    const auto _ULast = _Get_unwrapped(_Last);
    for (; _UFirst != _ULast; ++_UFirst)
        {
        _Val = _Reduce_op(_Val, *_UFirst); // <-- THIS IS WHERE THE WARNING IS
        }

    return (_Val);
    }

Any ideas what might be wrong?

1 Answers

25.9.2 Accumulate [accumulate] defines effect of std::accumulate as acc = std::move(acc) + *i. Since C++ for some reason does not support arithmetic operations on integer types smaller than int and instead promotes arguments on both sides of + into int prior to summing, result will be an int. Therefore you are getting a seemingly unavoidable warning here.

A possible workaround would be to define accumulator to be unsinged int and then cast final result to the desired type:

unsigned short res{static_cast< unsigned short >(::std::accumulate(shorts.begin(), shorts.end(), 0u));
Related