2

I'm using C++11 and STL. I have this piece of code:

std::set<std::string>::iterator it;
[...]
std::string &str = *it;

Compiler throws this error:

error: binding reference of type ‘std::__cxx11::string& {aka std::__cxx11::basic_string&}’ to ‘const std::__cxx11::basic_string’ discards qualifiers

Why is it happening?

Mat
  • 202,337
  • 40
  • 393
  • 406
class_OpenGL
  • 185
  • 1
  • 10
  • `set` only have `const_iterator`s. erase it, and insert a new element instead – sp2danny Dec 01 '17 at 14:54
  • 2
    Possible duplicate of [C++ STL set update is tedious: I can't change an element in place](https://stackoverflow.com/questions/2217878/c-stl-set-update-is-tedious-i-cant-change-an-element-in-place) – HolyBlackCat Dec 01 '17 at 14:55
  • or just add `const` before `std::string`, if you did not want to change the value – sp2danny Dec 01 '17 at 14:55
  • Why are defined iterator if it is actually const_iterator? Yes, I need to modify it. I couldn't find this post. Sorry – class_OpenGL Dec 01 '17 at 15:30
  • You can't modify an element in a `std::set`; that would upset the set's order. If you need to change it you have to remove it and insert a new one. – Pete Becker Dec 01 '17 at 15:42

1 Answers1

6

The keys in a set or map are const. If they were not, the set would not be able to provide its guarantee that elements are weakly ordered on the key. i.e. the would become inexplicably unsorted when users mutated the keys.

The std::set iterator dereferences to a key. Keys are (to reiterate) const.

Mutable references cannot bind to const references (language-imposed rule).

Therefore, either:

std::string const& str = *it;   // refer to the key

or

std::string str = *it;          // take a copy of the key
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
  • 1
    Ok, but why C++ defined iterator if it is actually a const_iterator? – class_OpenGL Dec 01 '17 at 15:48
  • @class_OpenGL: So that it is easy to iterate over the data. `iterator` alone does not imply mutability – AndyG Dec 01 '17 at 15:50
  • Ahh okk. Thanks!! – class_OpenGL Dec 01 '17 at 16:00
  • Or more specifically, `std::set::iterator` and `std::set::const_iterator` both exist to match the structure of all the other container templates where they are *not* identical. Similarly `std::set::key_type` is the same as `std::set::value_type`, and `std::set::key_compare` is the same as `std::set::value_compare` – Caleth Dec 01 '17 at 17:23