4

I am trying to create a symbol table where the key to the map is an identifier and the vector it returns contains pairs of strings representing type and scope, respectively. I am able to get a map with a string key return a vector of single strings to work, but when I try pairs, I get an error.

#include <iostream>
#include <utility>
#include <vector>
#include <map>
#include <string>
using namespace std; //using std namespace for readibility for this question

int main() {
    string key = "myKey";
    string string1 = "string1";
    string string2 = "string2";
    pair <string, string> stringPair = make_pair (string1, string2);

    map<string, vector<std::pair <string, string>>> myMap;
    myMap.insert( make_pair (key,  make_pair (string1, string2) )); //insert key into map, create empty vector
                                    //this is where I get th error

    myMap[key].push_back(std::make_pair (string1, string2) ); //use key, push strings into vector<string, string>

    return 0;
}

error C2664: 'std::pair<_Ty1,_Ty2> std::_Tree<_Traits>::insert(std::pair<const _Kty,_Ty> &&)' : cannot convert parameter 1 from 'std::pair<_Ty1,_Ty2>' to 'std::pair<_Ty1,_Ty2> &&'

I could get a vector of single strings to work, but that seems like more of a workaround than having true pairs for each instance of an identifier. Any help is appreciated!

2 Answers 2

5

Here is a very simple C++11 version that work but might be hard to read later, depends on the people:

#include <iostream>
#include <utility>
#include <vector>
#include <map>
#include <string>
using namespace std; //using std namespace for readibility for this question

int main() {
    string key = "myKey";
    string string1 = "string1";
    string string2 = "string2";
    map<string, vector<std::pair <string, string>>> myMap;

    myMap.insert( { key, {{ string1, string2 }} } ); 

    return 0;
}

Tested there: http://coliru.stacked-crooked.com/ (GCC4.8)

Of course if you want to add to the vector that contain the strings, you need to first check if the vector already exists. Here I am not checking if the vector already exists so if it does, there will be no insersion.

Sign up to request clarification or add additional context in comments.

Comments

4

The problem is that you're trying to insert a pair into the map, instead of a vector of pairs. If you want the vectors to start empty, the easiest way is to let it use the default constructor (which for a vector, makes an empty vector), and not explicitly insert into the map at all:

map<string, vector<std::pair <string, string>>> myMap;
myMap[key].push_back(std::make_pair (string1, string2) ); //use key, push strings into vector<string, string>

5 Comments

Oh, I see my error now. But I still need to insert explicitly to put the key in the map, right?
No, map::operator[] constructs a default value and inserts it if the key was not in the map previously. Since vector::vector() (the default ctor) gives an empty vector, that's exactly what you want.
Ok, I've got that working. On final question, if you would. How do I access the members in the vector pair? it->first refers to the key, but it->second.first doesn't work.
it->second is the vector. So it->second[0].first would be the first string in the first element of the vector
@Johnny that's why you should use helper variables with meaningful names: auto const& thevector = it->second; auto const& thepair = thevector[0]; auto const& thestring = thepair.first; (Of course there are better, semantic names). You don't have to break it up that far, but it->second[0].first is (obviously from your question) very obfuscating and hard to get your head around. iow: if it's hard to write, it's harder to read and maintain, so make it easier.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.