Reputation: 66214
I am writing a simple function that iterates over the numbers in a container and computes some summarizing value (the entropy in this case).
I want to write it as generic as possible, so that it works with different containers (vector
, set
, ...) over different value types (double
, float
, ...), so I'm doing this:
template<class Iterator>
typename Iterator::value_type Entropy(Iterator begin, Iterator end) {
typedef typename Iterator::value_type Value;
Value result = Value(); // assignment needed?
for (Iterator it = begin; it != end; ++it) {
result -= *it * log(*it);
}
return result;
}
I'm interested in what this code would look like according to all best practices. In other words, what exactly would an STL implementation of this little function look like?
Upvotes: 2
Views: 196
Reputation: 54178
In C++0x the following lambda version can be used:
template<class Iterator>
typename Iterator::value_type Entropy(Iterator begin, Iterator end) {
typedef typename Iterator::value_type Value;
return accumulate(begin, end, Value(),
[] (Value i, Value j)-> Value { return i - j * log(j); });
}
Upvotes: 4
Reputation: 40877
template < typename T1, typename T2 >
T1 entropy_sum(T1 sum_so_far, T2 number)
{
return sum_so_far - static_cast<T1>(number) * log(static_cast<T1>(number));
}
double entropy = std::accumulate(set.begin(), set.end(), 0.0, &entropy_sum<double, set_type::value_type>);
You method is OK except for the fact that Value()
might not be a legal statement.
Edited to reflect comment.
Upvotes: 4
Reputation: 41351
It would be better to use std::iterator_traits
for this:
typedef typename std::iterator_traits<Iterator>::value_type Value;
This allows Iterator to be a pointer.
Upvotes: 2