jeudi 26 février 2015

Get type from a templated range

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:



  1. std::begin() from the given entity

  2. std::end() from the given entity

  3. default-constructed value as a starting point

  4. 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