Reputation: 163
I have a two-dimensional map that I declared like that :
typedef std::map<std::string, std::map<std::string, Objective>> objectives_t;
I want to save the content of this 2d map into a file.
So I tried something like that, inspired by some code I found on the web :
for (auto const &subject : m_objectives) {
for (auto const &objective : m_objectives[subject.first]) {
//Print the objective
}
}
But of course, this doesn't work. How should I do that ? I'm not really sure what are subject and objective (are they some iterators ?).
On the second line, I get :
error: passing 'const objectives_t {aka const std::map<std::basic_string<char>, std::map<std::basic_string<char>, Objective> >}' as 'this' argument of 'std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = std::basic_string<char>; _Tp = std::map<std::basic_string<char>, Objective>; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::map<std::basic_string<char>, Obj|
Upvotes: 2
Views: 1687
Reputation: 275370
m_objectives
is const
in the above code.
operator[]
doesn't work on const
maps, because it is defined to modify the map if the key is not found.
So that is what your error is. Note that if it somehow modified the map, the outer loop would be screwed up, so the map being const was somewhat fortunate. As you have noted, it wouldn't actually modify it in this case (as you are feeding it keys back from itself).
The []
would be inefficient, regardless, as it generates an extra map lookup, when you have the value portion right there.
The fix is simple:
for (auto const &subject : m_objectives) {
for (auto const &objective : subject.second) {
//Print the objective
}
}
which is both correct (in that it doesn't use []
on a const map
), and faster (in that if you un-const
-ified the map
m_objectives
somehow, using []
while iterating over the map is both inefficient and error-prone).
Upvotes: 0
Reputation: 117856
Your outter loop is correct. But the inner should be iterating over subject.second
for (auto const &subject : m_objectives) {
for (auto const &objective : subject.second) {
// print out objective.second
}
}
This is because after the first range-based for loop, subject
has type
std::pair<const std::string, std::map<std::string, Objective>> const&
So each item is
subject.first // std::string
subject.second // std::map<std::string, Objective>
Then when you iterate over subject.second
, your objective
is now a
std::pair<const std::string, Objective> const&
So again to pull apart the elements
objective.first // std::string
objective.second // Objective
Upvotes: 9