c++ std::list compile issue? related to list.end() and list.end() - 1

Viewed 159

In below code.

int main() {
    list<int> m_list;
    m_list.push_back(1);
    list<int>::iterator it1 = (--m_list.end());   // it works, *it1 return 1;
    list<int>::iterator it2 = (m_list.end() - 1); // compile issue? 
}

Anybody explain why in list (m_list.end() - 1) has compile issue? and why (--m_list.end()) is OK? If we change to others, vector, string. both cases do work.

int main() {
    vector<int> m_vector;
    m_vector.push_back(1);
    vector<int>::iterator it1 = (--m_vector.end());   // both work
    vector<int>::iterator it2 = (m_vector.end() - 1); // both work 
}
2 Answers

The reason behind this is that list::end() returns a bidirectional iterator which does not support such operation.

Source:

http://www.cplusplus.com/reference/iterator/BidirectionalIterator/

On the other hand, vector::end() and string::end() returns a random access iterator which supports such operation.

http://www.cplusplus.com/reference/iterator/RandomAccessIterator/

Edit:

If you really want to accomplish the task, use std::prev() function

list<int>::iterator it2 = (std::prev(m_list.end(), 1));

As suggested by Pete Becker, "The second argument to std::prev has a default of 1"

So, you may do this also:

list<int>::iterator it2 = (std::prev(m_list.end()));

Anybody explain why in list (m_list.end() - 1) has compile issue?

Because list iterator doesn't support random access. Only random access iterators are guaranteed to support operator- (and operator+).

and why (--m_list.end()) is OK?

Because bidirectional iterators support operator-- (and operator++). List iterator is bidirectional.

If we change to others, vector, string. both cases do work.

Both vector and string have random access iterators.

Related