I've run into certain situations where an unordered_map
can't be passed into a function as const
&
, whereas in other situations this seems to be allowed. I'm unable to make sense of the errors in the cases where a compiler won't allow this. For example, consider this example program to count the number of connected components in a graph:
// NumConnectedComponents.cpp
#include <iostream>
#include <vector>
#include <unordered_map>
#include <unordered_set>
bool setContainsItem(const std::unordered_set<int>& S, int item)
{
if (S.find(item) == S.end()) return false;
else return true;
}
void countNumConnectedComponents2(int currentNode, const std::unordered_map<int, std::vector<int>>& graph, std::unordered_set<int>& visited)
{
visited.insert(currentNode);
std::vector<int> adjNodes = graph[currentNode];
for (auto& adjNode : adjNodes)
{
if (!setContainsItem(visited, adjNode))
{
countNumConnectedComponents2(adjNode, graph, visited);
}
}
}
int countNumConnectedComponents(int numNodes, const std::unordered_map<int, std::vector<int>>& graph)
{
std::unordered_set<int> visited;
int numConnComps = 0;
for (int i = 0; i < numNodes; i++)
{
if (!setContainsItem(visited, i))
{
countNumConnectedComponents2(i, graph, visited);
numConnComps++;
}
}
return numConnComps;
}
int main(void)
{
int numNodes = 5;
std::unordered_map<int, std::vector<int>> graph;
for (int i = 0; i < numNodes; i++)
{
graph[i] = std::vector<int>();
}
// add some edges
graph[0].push_back(3);
graph[3].push_back(0);
graph[1].push_back(2);
graph[2].push_back(1);
graph[4].push_back(2);
graph[2].push_back(4);
int numConnComps = countNumConnectedComponents(numNodes, graph);
std::cout << "\n" << "numConnComps = " << numConnComps << "\n\n";
return 0;
}
If I enter this program as above, on the line:
std::vector<int> adjNodes = graph[currentNode];
From the Visual Studio C++ compiler I get the error:
Error C2678
binary '[': no operator found which takes a left-hand operand of type 'const std::unordered_map<int,std::vector<int,std::allocator<int>>,std::hash<int>,std::equal_to<int>,std::allocator<std::pair<const int,std::vector<int,std::allocator<int>>>>>' (or there is no acceptable conversion)
In Ubuntu the gcc complier gives a similar error.
If I remove const
from the function signatures for countNumConnectedComponents2
and countNumConnectedComponents
(and leave everything else exactly the same) the program runs fine.
Can anybody explain this error, or what can be done to resolve it other than removing const
? I'd really like to use const when passing an unordered_map between functions if it should not be modified, and I need to retain the &
to avoid passing around copies of large maps.
Additionally I can't make rhyme or reason out of why in other situations const
is allowed for unordered_map
parameters, for example this program compiles and runs fine:
// SumUMapValues.cpp
#include <iostream>
#include <unordered_map>
int sumValsInMap(const std::unordered_map<int, int>& umap)
{
int sum = 0;
for (auto& element : umap)
{
sum += element.second;
}
return sum;
}
int main(void)
{
std::unordered_map<int, int> umap;
umap[1] = 10;
umap[2] = 20;
umap[3] = 30;
int sumOfVals = sumValsInMap(umap);
std::cout << "\n" << "sumOfVals = " << sumOfVals << "\n\n";
}