Cfon Cfon - 2 months ago 6
C++ Question

Automatically identify a suitable type, large enough and precise enough, to hold the sum of all elements in a container

(This question has been dramatically edited from the original, without changing the real intent of the original question)

If we add up all the elements in a

vector<int>
, then the answer could overflow, requiring something like
intmax_t
to store the answer accurately and without overflow. But
intmax_t
isn't suitable for
vector<double>
.

I could manually specify the types:

template<typename>
struct sum_traits;

template<>
struct sum_traits<int> {
typedef long accumulate_safely_t;
};


and then use them as follows:

template<typename C>
auto sum(const C& c) {
sum_traits<decltype(c.begin())> :: accumulate_safely_t> r = 0;
for(auto &el: c)
r += el;
return r;
}


My questions: Is it possible to automatically identify a suitable type, a large and accurate type, so I don't have to manually specify each one via the type trait?

Answer

You can use return type deduction in C++14 just like this:

template<typename C>
auto sum(const C& c) {
    auto r = 0;
    for(auto &el: c)
        r += el;
    return r;
}

In C++11, considering your C++98 code, you may use the following:

template<typename C>
auto sum(const C& c) -> typename C::value_type {
    auto r = 0;
    for(auto &el: c)
        r += el;
    return r;
}

But, as pointed in the comments, auto r = 0; will still resolve to int at compile time. As proposed in an other answer, you may want to make the initial value type (and so the return value type) a template parameter as well:

template<typename C, typename T>
T sum(const C& c, T init) {
    for(auto &el: c)
        init += el;
    return init;
}

// usage

std::vector<std::string> v({"Hello ", "World ", "!!!"});
std::cout << sum(v, std::string{});
Comments