user1868607
user1868607

Reputation: 2600

Type of elements in c++ map

I heard in this lecture about C++ associative containers that if you have a map like:

map<string,string> m;

its elements are of type:

pair<const string,string>

I have a little class representing phone number lists

PhoneList operator+(const PhoneList & g){
      PhoneList copy(*this);
      for(map<string,string>::const_iterator it = g.datos.begin(); it != g.datos.end(); ++it){
        copy.insert(*it);
      }
      return copy;
}

the problem is that insert method has the following header:

 pair<map<string,string>::iterator,bool>  insert(pair<string,string> p)

so apparently I'm converting a pair into a pair.

I would just like to know why this works. Is there a conversion between const string and string?

Upvotes: 5

Views: 2654

Answers (2)

Sam Varshavchik
Sam Varshavchik

Reputation: 118340

There are two reasons why your code works. First, because you're passing insert()'s parameters by value:

pair<map<string,string>::iterator,bool>  insert(pair<string,string> p)

If you were passing the parameter by reference instead, your code would like fail to compile:

pair<map<string,string>::iterator,bool>  insert(const pair<string,string> &p)

Passing non-trivial parameters by value is generally less efficient, but because here you are passing this parameter by value, the parameter gets, essentially, copy-constructed. That's the second reason. You end up using the following std::pair template constructor:

template<class U, class V> pair(const pair<U, V>& p);

Requires: is_constructible<first_type, const U&>::value is true and
is_constructible<second_type, const V&>::value is true.

Effects: Initializes members from the corresponding members of the
argument.

And that's why you are able to compile your code. To summarize, this template constructor allows std::pair<A, B> to be constructed from std::pair<C, D>, different classes, if A can be constructed from C, and B can be constructed from D. In your case A, B, and D are std::string, and C is a const std::string. And there's obviously not an issue with constructing a new std::string from some other std::string, it's an ordinary copy-constructor.

Upvotes: 4

Kirkova
Kirkova

Reputation: 347

The reason the elements are of type

pair<const string,string>

is to disallow you from changing the key in the map. When you insert a key-value pair into the map, the key is used to choose where in the internal data structure that the key-value pair should go. STL just doesn't let you change the key because then it would have to delete that element and reinsert it again with a different key. Sure they could have done this, but they didn't. You are able to change the value all you want, but the key will remain the same as it was originally made. You could always do this yourself if you needed to and copy the value, create a new key-value pair with the new key and the copied value, then delete the old key-value pair.

Also, you can simplify your code by using the range-based insert.

template <class InputIterator>
void insert (InputIterator first, InputIterator last);

This will just make your code look cleaner and why not take advantage of functions that already exist for you?

References: http://www.cplusplus.com/reference/map/map/insert/

Upvotes: 0

Related Questions