It is easy to iterate std::map and update values:
#include <iostream>
#include <map>
int main() {
std::map<int, int> m;
m[1] = 2;
m[2] = 4;
for (auto &[k, v] : m) {
v++; // <<< here
}
for (auto [k, v] : m) {
std::cout << k << ' ' << v << '\n';
}
return 0;
}
But std::flat_map in the same situation gives a compilation error:
#include <iostream>
#include <flat_map>
int main() {
std::flat_map<int, int> m;
m[1] = 2;
m[2] = 4;
for (auto &[k, v] : m) {
v++;
}
for (auto [k, v] : m) {
std::cout << k << ' ' << v << '\n';
}
return 0;
}
The compiler says:
2.cpp: In function 'int main()':
2.cpp:8:25: error: cannot bind non-const lvalue reference of type 'std::pair<const int&, int&>&' to an rvalue of type 'std::_Flat_map_impl<int, int, std::less<int>, std::vector<int, std::allocator<int> >, std::vector<int, std::allocator<int> >, false>::_Iterator<false>::reference' {aka 'std::pair<const int&, int&>'}
8 | for (auto &[k, v] : m) {
| ^
The only way to update the values I found was using const_cast, but it looks disgusting:
#include <iostream>
#include <flat_map>
int main() {
std::flat_map<int, int> m;
m[1] = 2;
m[2] = 4;
for (const auto &[k, v] : m) {
(*const_cast<int*>(&v))++;
}
for (auto [k, v] : m) {
std::cout << k << ' ' << v << '\n';
}
return 0;
}
What is the correct way to iterate std::flat_map updating values? I know I can do it using non-range-based for loop and/or iterators. But is it possible that the construct, added in the Standard 23, is not compatible with the range-based for loop?
auto && will match the const/volatile/ref state of each variable.
for (auto &&[k, v] : m) {
v++;
}