7

I just wrote a small helper function as a wrapper of std::accumulate:

template <typename FwdIter> inline
auto accumulate(FwdIter begin, FwdIter end) -> std::iterator_traits<FwdIter>::value_type
{
    return std::accumulate(begin, end, std::iterator_traits<FwdIter>::value_type());
}

I'm probably overlooking something here. Why isn't this an existing overload of std::accumulate ? The function appears so obvious that it can't have been overlooked; someone had a good reason to make that third parameter mandatory.

(See also Understanding std::accumulate - I understand why you want the ability to provide an initial value, I just don't understand why it is mandatory)

Community
  • 1
  • 1
MSalters
  • 173,980
  • 10
  • 155
  • 350

1 Answers1

7

So that the template arguments can be deduced.

The declaration is

template< class InputIt, class T >
T accumulate( InputIt first, InputIt last, T init );

and the only argument to deduce the return value from is init. Because it does not have to be value type of the iterator.

Yes, it could still default to std::iterator_traits<InputIt>::value_type(). The committee probably simply didn't think of that.

PS: You confused me with the auto. I thought it was not added because it was not possible in C++03 and overlooked when C++11 was done because it didn't look like needing any change. But it is not needed here; the template argument is declared at the time you write return type in the standard position.

Jan Hudec
  • 73,652
  • 13
  • 125
  • 172
  • That's not really an argument, though. If you want to use a non-default type, why not pass a type instead of a value: `template T accumulate(...); accumulate(begin, end);` – MSalters Sep 09 '13 at 09:05
  • 8
    @MSalters: Because all function templates in standard library deduce their arguments. Noone expects to specify them. Besides, than you don't save anything anymore -- `accumulate(...)` vs. `accumulate(...,T())`. – Jan Hudec Sep 09 '13 at 09:21