0

Turns out I don't really understand const.. So I have this (minimized) code sample. When I try to call a function which has access to members of a const class object (-> GetData()) I get the following error:

Error (gcc 11.2):

<source>:129:28: error: passing 'const std::unordered_map<int, A>' as 'this' argument discards qualifiers [-fpermissive]
  129 |         return some_data_[0];
      |                            ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/unordered_map:47,
                 from <source>:103:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/unordered_map.h:983:7: note:   in call to 'std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type& std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type&&) [with _Key = int; _Tp = A; _Hash = std::hash<int>; _Pred = std::equal_to<int>; _Alloc = std::allocator<std::pair<const int, A> >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type = A; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type = int]'
  983 |       operator[](key_type&& __k)
      |       ^~~~~~~~

Code:

#include <unordered_map>

class A
{

public:

    A() : cnt_(0) {}
    A(int cnt) : cnt_(cnt) {}

    int& GetCnt() {
        return cnt_;
    };

private:
    int cnt_;
};

class B
{
public:
    B(int nr) {
        some_data_ = { { 0, A(nr) } };
    }

    const A& GetData() const {
        return some_data_[0];
    }

private:
    std::unordered_map<int, A> some_data_;
};

int main()
{
    const B b_obj(2);

    b_obj.GetData();
}

Do I understand correctly that

  1. When I define a class type object const, all members become const as well?
  2. All members const means also that somehow this constness translates to unoredered_map-contents being const? If so, how? Is there some template magic behind it to add the qualifier?
  3. If the above assumptions are correct, how else than through a const X const function do I pass read-only access to members of the const class (map value in this case) to an outside function?
glades
  • 3,778
  • 1
  • 12
  • 34
  • `some_data_[0]` may atempt to modify the const map. You want `some_data_.at(0);`. – 273K Feb 21 '22 at 15:18
  • @273K: Yes but do I not avoid that by making it a const member function (that supposedly doesn't change members)? Does the compiler see through that? – glades Feb 21 '22 at 15:22
  • 1
    `map::operator[]` is not a const method, may not be called for a const map. – 273K Feb 21 '22 at 15:36
  • @273K ahh I understand. Making the container const makes member `some_data_` const as well which doesn't allow index access []. How could I then write a second method with `at()` which only kicks in if the container is const? – glades Feb 21 '22 at 17:27
  • You could have two overloads of `B::GetData`, one with `const` modifier (which would be called on `const B` instance) and one without (which would be called on non-const `B` instance). If that's what you are looking for; I'm not sure I understand the question in your last comment. – Igor Tandetnik Feb 21 '22 at 20:17
  • @IgorTandetnik I think you understood me correctly that is what I'm looking for, thank you! :) – glades Feb 22 '22 at 06:35

0 Answers0