Reputation: 9196
What is the form (if there is one) to write template functions, where arguments are templated containers?
For example I want to write a generic sum, which will work on any container which can be iterated over. Given the code below I have to write for example sum<int>(myInts)
. I would prefer to just write sum(myInts)
and the type to be inferred from the type which myInts contains.
/**
@brief Summation for iterable containers of numerical type
@tparam cN Numerical type (that can be summed)
@param[in] container container containing the values, e.g. a vector of doubles
@param[out] total The sum (i.e. total)
*/
template<typename N, typename cN>
N sum(cN container) {
N total;
for (N& value : container) {
total += value;
}
return total;
}
Upvotes: 1
Views: 194
Reputation: 208446
This, even if cumbersome, can do the trick in C++11:
template <typename C>
auto sum( C const & container )
-> std::decay<decltype( *std::begin(container) )>::type
Another option is just using the same structure that accumulate does: have the caller pass an extra argument with the initial value and use that to control the result of the expression:
template<typename N, typename cN>
N sum(cN container, N initial_value = N() )
(By providing a default value, the user can decide to call it with a value or else provide the template argument --but this requires the type N to be default constructible)
Upvotes: 0
Reputation: 16168
I write such a function like this
template<typename IT1>
typename std::iterator_traits<IT1>::value_type //or decltype!
function(IT1 first, const IT1 last)
{
while(first != last)
{
//your stuff here auto and decltype is your friend.
++first;
}
return //whatever
}
This way it will work with more than just containers, for example ostream iterators and directory iterators.
Call like
function(std::begin(container), std::end(container));
Upvotes: 3