7

Fetching an entry from a const C++ std::map fails to compile on gcc 5.4.0.

test_map.cpp: In function ‘int main()’:
test_map.cpp:9:24: error: passing ‘const std::map<int, int>’ as ‘this’ argument discards qualifiers [-fpermissive]
                 foo[key];

Minimal test case

// Compile with
// g++ test_map.cpp -o test_map

#include <map>

int main() {
    const std::map<int, int> foo;
    foo[0]; // compiles if "const" above is suppressed
}

Look before you post

This looks similar to passing ‘const this argument discards qualifiers [-fpermissive] which is about a Cache, not a std::map. The cause there: the user calls a write() method. That method is not declared const which makes sense since writing presumably modified the object.

But here, fetching an element from a map does not modify the map, does it?

Question

The actual map in my real use case is indeed const. It's fully initialized in the source code. It does not make sense to modify it. Declaring it non-const practically solves the problem but does not make sense.

Community
  • 1
  • 1
Stéphane Gourichon
  • 6,493
  • 4
  • 37
  • 48
  • 6
    `operator[]` does not fetch anything from a map, it returns a mutable reference to a value in the map. As such, it cannot be used in a `const` map instance. – Sam Varshavchik Feb 07 '17 at 17:01
  • 2
    @SamVarshavchik more importantly, it inserts a value if the key isn't present. That's why it can't be used on a const map. – Jonathan Wakely Feb 07 '17 at 17:09
  • _But here, fetching an element from a map does not modify the map, does it?_ Did you even try to read the documentation? – Algirdas Preidžius Feb 07 '17 at 17:16
  • @SamVarshavchik Your comment is the best answer. Also, an access operator that inserts elements seems one of the silliest things in a language such as C++ where things aims to be minimal, memory and cpu-parsimonius and you're supposed to pay only for what you use. Even C# has this right. Thank you for pointing that. – Stéphane Gourichon Feb 07 '17 at 17:26
  • @juanchopanza I have searched for relevant keywords and phrases in Google then in stackexchange itself, have read several questions and answers (probably 5 or 6), but surprisingly the pre-existing question did not show up at the time. – Stéphane Gourichon Feb 07 '17 at 21:14
  • @StéphaneGourichon Yes, unfortunately it is easy to find duplicates... if you already know the answer. – juanchopanza Feb 07 '17 at 21:36
  • 2
    I do not find @StéphaneGourichon posed a stupid question at all, and I do not think it is a duplicate: It wasn't directly clear to me either that `operator[]` cannot be used an `const` map instances. The error message returned also differs from the 5+ other "similar" questions: Note that there is no specification of the `argument`. – Toon Aug 31 '18 at 11:41

1 Answers1

19

operator[] doesn't have a const qualifier in std::map, as you can see from the documentation, e.g. std::map::operator[] - cppreference.com:

Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.

Therefore you cannot use it directly on a const instance. Use at instead (ref std::map::at - cppreference.com) if you can afford C++11 features.

Declarations for those member functions follow:

T& operator[](const key_type& x);
T& operator[](key_type&& x);
T&       at(const key_type& x);
const T& at(const key_type& x) const;
Brunisboy
  • 123
  • 1
  • 19
skypjack
  • 49,335
  • 19
  • 95
  • 187
  • I forgot in C++ map, looking up a key that does not exist added the key to the map. Makes sense in some context, but not obvious to me! Ty for this answer now I understand this error I'm also hitting. – Bill Gale Nov 17 '21 at 16:20