In this question the OP asks why his std::accumulate
function is returning the wrong value. The answer is because he passes in an int
for his initial value, therefore making the calculations all int
s rather than double
s. I have two versions:
template <class InputIterator, class T>
auto accumulate (InputIterator first, InputIterator last, T init)
{
typedef typename std::iterator_traits<InputIterator>::value_type vt;
vt init2 = vt(init);
// ...
return init2;
}
template <class InputIterator, class T = typename std::iterator_traits<InputIterator>::value_type>
T not_working (InputIterator first, InputIterator last, T init)
{
// ...
return init;
}
Why in version 2 is T
still an int
? Because of implicit conversion?
The answer to the immediate question was already stated: if the type can be deduced from the argument list, it will be deduced. Making the used type a nested type prevents it from being deduced:
template <typename T>
struct identity {
typedef T type;
};
template <typename It, typename T = typename std::iterator_traits<It>::value_type>
T safe_accumulate(It begin, It end, typename identity<T>::type sum) {
return std::accumulate(begin, end, sum);
}
In some situations it is, however, desirable to specify the result type of the algorithm. For example, if you want to sum the char
values in a lengthy strings. Using safe_accumulate()
as it is defined above makes specifying the result type a bit painful:
std::string s("hello, world");
std::cout << safe_accumulate<std::string::iterator, long>(s.begin(), s.end(), 0) << '\n';
The implementation can be done in a way which puts the result type first:
template <typename T = void, typename It>
typename std::conditional<std::is_same<T, void>::value,
typename std::iterator_traits<It>::value_type,
T>::type
safe_accumulate(It begin, It end,
typename std::conditional<std::is_same<T, void>::value,
typename std::iterator_traits<It>::value_type,
T>::type sum) {
return std::accumulate(begin, end, sum);
}
Now the algorithm can be used in a more convenient way, i.e., the implementer of the algorithm provided a somewhat more complicated implementation for the benefit of its users:
std::cout << safe_accumulate<long>(s.begin(), s.end(), 0) << '\n';
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments