Hey, it's me again. Again with a topic that has been covered here but reading through the old threads didnt help me to solve my problem. And I am pretty clueless at the moment.

Consider the class passenger_queue with 2 functions, namely:

int passenger_queue::get_passengers_waiting() const
{
  // Insert your code here. Use the iterator defined in this class.
  int sum = 0;

  }
  return sum;


}

and

std::vector<passenger*>& passenger_queue::passengers_at_floor(int floor_)
{
    return _waiting_passengers[floor_];
}

member variables are:

typedef std::map<int, std::vector<passenger*> >  p_map;
  p_map _waiting_passengers;
    
  std::vector<passenger> _passengers;

First of all the comment in the get_passengers_waiting. Apart from the constructor which I didnt include in the code, there is no iterator defined in this class (or else I dont know how an iterator definition looks like).

So my first solution is the following (which seems to work):

int passenger_queue::get_passengers_waiting() const
{
  // Insert your code here. Use the iterator defined in this class.
  int sum = 0;
  for (p_map::const_iterator it = _waiting_passengers.begin(); it != _waiting_passengers.end(); ++it) {
    sum+= it->second.size();
  }
  return sum;
}

I dont need the function passengers_at_floor at all. Now I think the idea would be to use that function but then I run into trouble - passing const as this discards qualifiers. hence the title. What I try is the following:

int passenger_queue::get_passengers_waiting() const
{
  // Insert your code here. Use the iterator defined in this class.
  int sum = 0;
  for (p_map::const_iterator it = _waiting_passengers.begin(); it != _waiting_passengers.end(); ++it) {
    sum+= passengers_at_floor((it->first)).size();
  }
  return sum;
}

which gives me the error:

error: passing ‘const passenger_queue’ as ‘this’ argument of ‘std::vector<passenger*, std::allocator<passenger*> >& passenger_queue::passengers_at_floor(int)’ discards qualifiers

I tried to use iterator instead of const_iterator but that doesnt go down well with the const in the get_passengers_waiting(). So honestly I wouldnt know how to get to the correct result with the use of the passengers_at_floor().

Can anyone point me in the right direction?

I appreciate any help and I hope I wasnt too messy.

(If mike is reading this - I hear you, no leading _ but its still from the same assignment paper :))

Recommended Answers

All 11 Replies

It could be this function

std::vector<passenger*>& passenger_queue::passengers_at_floor(int floor_)

Try changing it to

std::vector<passenger*>& passenger_queue::passengers_at_floor(const int floor_)

I just tried that but I didnt help. But am I right assuming that it->first is a const int due to the iterator being constant and you wanted to match parameters?

I just tried that but I didnt help. But am I right assuming that it->first is a const int due to the iterator being constant and you wanted to match parameters?

I was mistaken, because the function

std::vector<passenger*>& passenger_queue::passengers_at_floor(int floor_)

makes a copy of the const data member first, its allowed.

I suspect the solution is

std::vector<passenger*>& passenger_queue::passengers_at_floor(int floor_) const

The point is that at present, passengers_at_floor is permitted to modify its object, but you're passing it a const object, namely the key from a map.

So you need to add const to the definition of passengers_at_floor, as a promise that it will not modify its object. Of course you need to add it to the declaration inside the class as well, not just to the definition.

This function:

std::vector<passenger*>& passenger_queue::passengers_at_floor(int floor_) const

Has a big flaw, which results in the error you are getting. Since the function is const, it means that you only have read-only access to all its data members. But then, you try to return a non-const reference to a data member from that function. This simply cannot work, and hence, the error you get (either you put the const at the end and you get a "discards qualifiers" on the return type, or you don't put the const and you get a "discards qualifiers" on the this pointer when the function is called). The solution is simple, define both versions:

//make a non-const function that returns a non-const reference: 
std::vector<passenger*>& passenger_queue::passengers_at_floor(int floor_);
//make a const function that returns a const reference:
const std::vector<passenger*>& passenger_queue::passengers_at_floor(int floor_) const;

Both implementations of the above functions are exactly the same. When you call the function with a const object, the const function will be called and a const reference will be returned (and vice-versa if called with a non-const object). This is the proper, and usual way to do this.

I suspect the solution is

std::vector<passenger*>& passenger_queue::passengers_at_floor(int floor_) const

The point is that at present, passengers_at_floor is permitted to modify its object, but you're passing it a const object, namely the key from a map.

So you need to add const to the definition of passengers_at_floor, as a promise that it will not modify its object. Of course you need to add it to the declaration inside the class as well, not just to the definition.

Agreed. The OP is trying to call a non-const function from a const function. That's not allowed...

//make a non-const function that returns a non-const reference: 
std::vector<passenger*>& passenger_queue::passengers_at_floor(int floor_);
//make a const function that returns a const reference:
const std::vector<passenger*>& passenger_queue::passengers_at_floor(int floor_) const;

So if I understood correctly:

I declared the const and non const version of this function in the header and implemented both in the cpp file. The function body is the same.

If I do this and then compile I get the following error: /Users/phi/Desktop/task_4/passenger_queue.cpp:38:0 /Users/phi/Desktop/task_4/passenger_queue.cpp:38: error: passing 'const std::map<int, std::vector<passenger*, std::allocator<passenger*> >, std::less<int>, std::allocator<std::pair<const int, std::vector<passenger*, std::allocator<passenger*> > > > >' as 'this' argument of '_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = int, _Tp = std::vector<passenger*, std::allocator<passenger*> >, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, std::vector<passenger*, std::allocator<passenger*> > > >]' discards qualifiers

Oh, that's right, if you use a std::map, the operator[] does not exist in the const form because if the index (or key value) does not exist, a new element will be created. So, for the const version, you need to use the find() function instead which will just find the element corresponding to a key (or an invalid iterator if the key does not exist).

Sorry its me again. Trying to access the map with find gives me following error: error: invalid initialization of reference of type 'const std::vector<passenger*, std::allocator<passenger*> >&' from expression of type 'std::_Rb_tree_const_iterator<std::pair<const int, std::vector<passenger*, std::allocator<passenger*> > > >' the function looks like this. Sorry, I just dont seem to get it.

const std::vector<passenger*>& passenger_queue::passengers_at_floor(int floor_) const
{
    return _waiting_passengers.find(floor_);
}

The find function returns a const_iterator in the map, you have to check that it is valid and then output it, and you also have to deal with the fact that the iterator might be invalid if the element does not exist in the map.

const std::vector<passenger*>& passenger_queue::passengers_at_floor(int floor_) const
{
  std::map< std::vector<passenger*> >::const_iterator it = _waiting_passengers.find(floor_);
  if(it != _waiting_passengers.end())
    return *it;
  else
    return std::vector<passenger*>(); //or throw an exception.
}

It works!
Thanks everyone for their big help.

fibbo

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.