How to assign a value in const unordered_map to another const variable - C++

Viewed 302
#include <iostream>
#include <bits/stdc++.h>
using namespace std;

void fun(const unordered_map<int, vector<int>>& direct_paths) {
    const int var = direct_paths[1][0];
    cout << var;
}

int main()
{
    unordered_map<int, vector<int>> a;
    a[1] = vector<int> {1,2,3};
    fun(a);
    return 0;
}

The above code outputs the following error:

error: passing ‘const std::unordered_map<int, std::vector<int> >’ as ‘this’ argument discards qualifiers [-fpermissive]
  const int var = direct_paths[1][0];
                                ^

Where as The below code doesn't output any compilation error:

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

void fun(const vector<int>& direct_paths) {
    const int var = direct_paths[1];
    cout << var;
}

int main()
{
    vector<int> a;
    a = vector<int> {1,2,3};
    fun(a);
    return 0;
}

Questions:

  1. Can I assign the value in a key-value pair of an unordered_map somehow?
  2. Why is assigning an integer from vector taken from const unordered_map<int, vector&> disallowed? & from const vector allowed?

Thanks in advance!

1 Answers

The operator[] of a std::(unordered_)map is a non-const operator only, as it will modify the map to insert a new element if the requested key is not found. But inside of fun(), direct_paths is (a reference to) a const map object, so operator[] cannot be called on it. That is what the compiler is complaining about, as you can't call non-const methods on const objects.

The operator[] of std::vector has no such limitation, as it is overloaded to work with both const and non-const vector objects.

To fix the error you are seeing, you will need to use the map's at() or find() method instead, which can both be called on const map objects, eg:

void fun(const unordered_map<int, vector<int>>& direct_paths) {
    const int var = direct_paths.at(1)[0]; // will throw an exception if key '1' is not found...
    cout << var;
}
void fun(const unordered_map<int, vector<int>>& direct_paths) {
    auto iter = direct_paths.find(1); // will return the end() iterator if key '1' is not found...
    if (iter == direct_paths.end()) return; // or throw...
    const int var = iter->second[0];
    cout << var;
}
Related