I wrote a function that finds the most common element in any given container (see code below), where the input are two const_iterators for that container. If I call this function however with findMostFrequent(ivec.begin(), ivec.end()) where ivec is a vector<int>, the compiler cannot deduce the template arguments. Calling the function with findMostFrequent< vector<int> >(ivec.begin(), ivec.end()) works fine, but it seems cumbersome. Is there a way to let the compiler find out which template to instantiate?
template <typename T> typename T::value_type findMostFrequent(typename T::const_iterator beg, typename T::const_iterator end)
{
// T is the type of container, T::value_type is the type which is stored in the container
typename T::size_type current_streak = 0, max_streak = 0;
T::value_type max_so_far;
for (T::const_iterator iter = beg; iter != end; ++iter)
{
current_streak = count(beg, end, *iter);
if ( current_streak > max_streak )
{
max_so_far = *iter;
max_streak = current_streak;
}
}
return max_so_far;
}
The compiler can not deduce nested specifiers. “Find me a type that has a nested specifier that is equal to the type that I see as a parameter” is too complicated and often ambiguous to resolve it easily. Instead, try to deduce everything you need to know from the iterators directly:
The reason why you should use
std::iterator_traits<T>::value_typeinstead ofT::value_typeis that it enables you to also have these “iterator specifications” for types that do not naturally define them, such as pointers. For example,T*is actually a valid iterator for this snippet, but it does not contain avalue_typetypedef/type.