Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deducing value type from iterator for return type of template function

Just experimenting with multiple return values using this simple snippet that calculates sum and mean from a container.

template<typename Iter>
std::tuple<double, double> summean(Iter first1, Iter last1)
{
    double sum = std::accumulate(first1, last1, 0.0);
    double mean = sum / (last1-first1);

    return {sum, mean};
}

The demo uses double precision calculation just as a demo. Is there an elegant way to use the precision of the values in the container in the calculations for the return types of the tuple?

like image 654
learnvst Avatar asked Dec 05 '25 04:12

learnvst


2 Answers

You can use std::iterator_traits::value_type:

typedef typename std::iterator_traits<Iter>::value_type value_type;

As for the function declaration and definition, in old-school C++03 style you could do the following:

template<typename Iter>
std::pair<typename std::iterator_traits<Iter>::value_type,
          typename std::iterator_traits<Iter>::value_type> 
summean(Iter first1, Iter last1)
{
    typedef typename std::iterator_traits<Iter>::value_type value_type;
    value_type sum = std::accumulate(first1, last1, value_type());
    value_type mean = sum / (last1-first1);

    return std::make_pair(sum, mean);
}

And since C++11 you can use decltype and trailing return type to make it less verbose:

template<typename Iter>
auto summean(Iter first1, Iter last1)->decltype(std::make_tuple(*first1, *first))
{
    using value_type = typename std::iterator_traits<Iter>::value_type;
    value_type sum = std::accumulate(first1, last1, value_type());
    value_type mean = sum / (last1-first1);

    return make_tuple(sum, mean);
}
like image 181
juanchopanza Avatar answered Dec 07 '25 18:12

juanchopanza


You probably want to return a std::pair of double instead of std::tuple. As for your problem you can use the value_type member taken from std::iterator_traits:

template<typename Iter>
auto
summean(Iter first1, Iter last1) -> decltype(std::make_pair(*first1, double{}))
{
    using value_type = typename std::iterator_traits<Iter>::value_type;
    double sum = std::accumulate(first1, last1, value_type{});
    double mean = sum / (last1-first1);

    return {sum, mean};
}
like image 35
David G Avatar answered Dec 07 '25 19:12

David G