I'm trying to implement a wrapper around std::accumulate
algorithm, so that instead of typing this:
std::accumulate(v.begin(), v.end(), 0, [](int x, int y) { return x * y; });
user can simply write this:
my::accumulate(v, [](int x, int y) { return x * y; });
So basically, my::accumulate
, given an entity and an operation, is intended to call std::accumulate
with the following arguments:
std::begin()
from the given entitystd::end()
from the given entity- default-constructed value as a starting point
- given operation
I use free begin
and end
functions to allow function work on built-in arrays. The passed entity is thus a range. Here is my implementation:
template<class R, typename F>
auto accumulate(const R& r, F&& f) ->
typename std::iterator_traits<decltype(std::begin(r))>::value_type
{
using T = std::iterator_traits<decltype(std::begin(r))>::value_type;
return std::accumulate(std::begin(r), std::end(r), T{}, std::forward<F>(f));
}
It works fine. The only thing that bothers me is that ugly std::iterator_traits<decltype(std::begin(r))>::value_type
construction. Is there a better way to get the type from the range?
Please note, that I'm using Visual Studio 2013, so I can use most of C++11 and some of C++14.
PS. Any other comments on the implementation? Are there any drawbacks or implications?
Aucun commentaire:
Enregistrer un commentaire