Hamza Asif
Hamza Asif

Reputation: 76

Calculate the sum between two iterators in STL containers

I am working on a problem in STL containers:

Create a Sum() function that calculates the sum between two iterators. The function then uses the template argument for the iterator type and accepts two iterators, the start and the end

I am trying to write the following code but I am not understanding the problem can anyone help me please .

template <typename type , typename start , typename  end>
double sum(type& t, start& s , end& e) 
{
  typename t::const_iterator i;
  double sum = 0;
  for (i = s  ; i != e; ++i)
    {
      sum+=*i;
    }
  return sum;
}


int main()
{
  //for list 
  list<double> l; //creat a double type list
  l.push_back(10); //pushing data into list l
  l.push_front(11);//pushing data into list l
  l.push_back(9);//pushing data into list l
  l.push_front(12);//pushing data into list l
  l.push_back(8);//pushing data into list l
  list<double>::iterator itlist;

   cout<<"Sum of List L is : "<< sum( itlist , l.begin() , l.end())<<endl;
}

I don't think i am doing correct. i have got many errors. one of my error is:

no instance of overloaded function "sum" matches the argument list -- argument types are: (std::_List_iterator<double>, std::_List_iterator<double>, std::_List_iterator<double>)

Upvotes: 0

Views: 578

Answers (2)

gsamaras
gsamaras

Reputation: 73394

One approach you could try is to pass const references to start and end of the iterators. Moreover, just one typename is enough, you can discard the others.

Then this typename t::const_iterator i; doesn't make sense, because t is a variable. To answer your comment, you cannot do typename type::const_iterator i; either.

Easiest solution would be to discard that problematic line of the const iterator, and use the auto keyword in the for loop.

Putting everything together, you get this:

template <typename T>
double sum(T const& start, T const& end) 
{
  double sum = 0;
  for(auto i = start; i != end; ++i)
  {
    sum+=*i;
  }
  return sum;
}

which is called like this:

cout << "Sum of List L is: "<< sum(l.begin() , l.end()) << endl;

and outputs (Run it Online):

Sum of List L is: 50

Alternative: @cigien's answer, which passes the iterators by value instead of reference, which is the typical method of passing iterators - I was just trying to stick as close as possible to OP's code.


To answer your comment:

Create a Sum() function that calculates the sum between two iterators. The function then uses the template argument for the iterator type and accepts two iterators, the start and the end.

Then you could simply use the typename T instead of the auto keyword, like this:

template <typename T>
double sum(T const& start,T const& end) 
{
  double sum = 0;
  for(T i = start; i != end; ++i)
  {
    sum+=*i;
  }
  return sum;
}

Run it Online

Upvotes: 0

cigien
cigien

Reputation: 60268

There are a number of issues with your code. In this function:

template <typename type , typename start , typename  end>
double sum(type& t, start& s , end& e) 

you are taking s and e by reference. But this can't bind to l.begin() or l.end(), since they return r-values.

Iterators are generally passed around by copy anyway, so you can simply write:

template <typename type , typename start , typename  end>
double sum(type& t, start s , end e) 

You also have an issue here:

typename t::const_iterator i;

You can't do this because t is a variable, not a type.

However, you don't need to spell out the type of i at all. Instead, you could simply write:

for (auto i = s  ; i != e; ++i)
{
  // ...
}

and let the compiler deduce the type of i.


In fact, there is no need to pass itlist to your function at all, since all the needed information is in the other arguments. Also, since both arguments have the same type, you only need one template parameter.

So now your function would simply be

template <typename iter>    // a single template argument
double sum(iter s , iter e) // 2 function arguments, both of the same type
{
  // ...
}

and you would call it like this:

sum(l.begin() , l.end())

Here's a demo.

Upvotes: 3

Related Questions