code_fodder code_fodder - 2 months ago 19
C++ Question

C++11 range based multimap loop - cant return a non const pair

I can't seem to see what I am doing wrong here and getting out of my depth a little.

What I have is some data structures containing vectors and multimaps.

I want to make second vectors/multimaps that contain pointers to the original data so that if I edit the second vector/map the data is change in the original. Reason for this is that the list is a temporary sub-set of the orig based on some criteria.

First I tried this on vectors and it seems to work, here is a working example:

std::vector<std::string> strVect;
strVect.push_back("test1");
strVect.push_back("test2");
strVect.push_back("test3");
std::vector<std::string *>strpVect;
for (std::string &str : strVect)
{
strpVect.push_back(&str);
}


Here, elements in strpVect point to the originals in strVect.

Now I want to do the same sort of thing for multimaps:

std::multimap<int, std::string> strMap;
strMap.insert(std::pair<int, std::string>(1, "test1"));
strMap.insert(std::pair<int, std::string>(2, "test2"));
strMap.insert(std::pair<int, std::string>(3, "test3"));
std::multimap<int, std::string *>strpMap;
for (std::pair<int, std::string> &val : strMap) // <<<<< error here
{
strpMap.insert(std::pair<int, std::string *>(val.first, &val.second));
}


Now when I run this I get the error
invalid init of non-const reference of type std::pair....


If I make it a const then it works:

std::multimap<int, std::string> strMap;
strMap.insert(std::pair<int, std::string>(1, "test1"));
strMap.insert(std::pair<int, std::string>(2, "test2"));
strMap.insert(std::pair<int, std::string>(3, "test3"));
std::multimap<int, std::string *>strpMap;
for (const std::pair<int, std::string> &val : strMap)
{
strpMap.insert(std::pair<int, std::string *>(val.first, &val.second)); // <<<<< error here
}


But then I get an error (more obviously for me) on my insert - but I don't want to insert a const because I want to change the values inside.... I could cast it away, but I see this as a failure of my coding :(

Answer

The key in a (multi)map is const. Thus,

for (std::pair<const int, std::string> &val : strMap)
{
    strpMap.insert(std::pair<int, std::string *>(val.first, &val.second));
}

should do the trick.

Or, even better, use auto:

for (auto &val : strMap)
{
    strpMap.insert(std::pair<int, std::string *>(val.first, &val.second));
}

This automatically gets the const right for you.