feelfree
feelfree

Reputation: 11753

a template function for obtaining the maximum value as well as its corresponding index in a vector

It is not difficult to write a function that can give you the maximum value as well as its corresponding index in a vector array as the following codes show:

using namespace std;



std::vector<double> line_weighting;
line_weighting.push_back(22);
line_weighting.push_back(8);
line_weighting.push_back(55);
line_weighting.push_back(19);



std::vector<double>::iterator   it =  std::max_element(line_weighting.begin(),line_weighting.end());
int index = distance(line_weighting.begin(),it);
value = *it;

I am more interested in a more general function using template that can perform the same kind of functionality:

template<typename T>
     int max_with_index(const std::vector<T> &weighting, T &max_value)
     {
         std::vector<T>::iterator  it = max_element(weighting.begin(),weighting.end());
         max_value =   *it;
         return (std::distance(weighting.begin(),it));
     }

However, this function cannot compile as it has the following error in VC2010:

Error   2   error C2782: 'iterator_traits<_Iter>::difference_type std::distance(_InIt,_InIt)' : template parameter '_InIt' is ambiguous 
Error   1   error C2440: 'initializing' : cannot convert from 'std::_Vector_const_iterator<_Myvec>' to 'std::_Vector_iterator<_Myvec>'

I know that if I write this function this way, it can work.

  template<typename T>
     int max_with_index(const std::vector<T> &weighting, T &max_value)
     {
        // std::vector<T>::iterator  it = max_element(weighting.begin(),weighting.end());
         auto  it= max_element(weighting.begin(),weighting.end());
         max_value =   *it;
         return (std::distance(weighting.begin(),it));
     }

But I cannot understand why my original implementation has compilation error, and can I do something to correct it?

Upvotes: 1

Views: 251

Answers (2)

Motti
Motti

Reputation: 114725

Vector has two types of iterators, const_iterator and regular iterator, these are different types and therefore can't be converted from one to the other.

You should change

  std::vector<T>::iterator  it = ...

To

  std::vector<T>::const_iterator  it = ...

Or better yet let the compiler do the work for you:

  auto  it = ...

Upvotes: 1

billz
billz

Reputation: 45410

You are trying to compare different types of iterators, you need to use const_iterator as weighting is const

std::vector<T>::const_iterator  it = max_element(weighting.begin(),weighting.end());

That's why auto is so good in C++11.

Upvotes: 2

Related Questions