Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are const iterators still evil in C++14

Item 26 from Scott Mayers's "Effective STL" is labeled "Prefer iterator to const_iterator, reverse_iterator and const reverse iterator".

The reasoning is that some forms of insert() and erase() require exactly iterator and converting from the other types is tedious and error-prone. Furthermore, comparing iterator and const_iterator could be problematic, depending on the STL implementation.

The book was released at 2001. Is the advice in Item 26 still valid with the current state of gcc?

like image 522
Vorac Avatar asked Sep 11 '14 09:09

Vorac


2 Answers

The C++14 standard (N3936) guarantees that iterator and const_iterator are freely comparable (§23.2.1 [container.requirements.general]/p7):

In the expressions

i == j
i != j
i < j
i <= j
i >= j
i > j
i - j

where i and j denote objects of a container’s iterator type, either or both may be replaced by an object of the container’s const_iterator type referring to the same element with no change in semantics.

In addition, the container member functions take const_iterator parameters as of C++11 (§C.2.13 [diff.cpp03.containers] - as might be inferred from the tag, this is a change from C++03):

Change: Signature changes: from iterator to const_iterator parameters

Rationale: Overspecification. Effects: The signatures of the following member functions changed from taking an iterator to taking a const_iterator:

  • insert(iter, val) for vector, deque, list, set, multiset, map, multimap
  • insert(pos, beg, end) for vector, deque, list, forward_list
  • erase(iter) forset,multiset,map,multimap`
  • erase(begin, end) forset,multiset,map,multimap`
  • all forms of list::splice
  • all forms of list::merge

The container requirements have been similarly changed to take const iterators. In addition, it is easy to obtain the underlying iterator from a std::reverse_iterator via its .base() member function. Thus, neither of the concerns noted in the question should be an issue in a conforming compiler.

like image 111
T.C. Avatar answered Oct 04 '22 09:10

T.C.


The advice has been reversed, as can be seen from Item 13 of the upcoming Effective Modern C++ which is titled:

Prefer const_iterators to iterators

The reason is that C++11 and C++14 add several tweaks that make const_iterators a lot more practical:

C++11 adds

  • member functions cbegin() and cend() (and their reverse counterparts) for all Standard Library containers
  • member functions using iterators to identify positions (e.g. insert(), erase()) now take a const_iterator instead of an iterator

C++14 completes that by adding non-member cbegin() and cend() (and their reverse counterparts)

like image 39
TemplateRex Avatar answered Oct 04 '22 10:10

TemplateRex