19

I am initializing map<string, vector<string> > as follows:

map <string, vector<string> > dict;

dict["USA"].push_back("NYC");
dict["USA"].push_back("LA");
dict["USA"].push_back("Chicago");
dict["USA"].push_back("Dallas");

dict["India"].push_back("Delhi");
dict["India"].push_back("Bombay");

dict["Australia"].push_back("Melbourne");
dict["Australia"].push_back("Sydney");
dict["Australia"].push_back("Adelaide");

I find this cumbersome. The same thing can be done in tcl as follows which is cleaner:

array set dict {
USA {NYC LA Chicago Dallas}
India {Delhi Bombay}
Australia {Melbourne Sydney Adelaide}
}

Is there a more cleaner way to initialize in C++? My compiler is gcc 3.4.6

2
  • 7
    In C++11, yes. In GCC 3.4.6, no. Commented Mar 30, 2012 at 21:40
  • 2
    GCC 3.4.6??? You should really consider upgrading to a newer compiler... There is a boost library to ease this type of initialization but I am not sure that it can be used with such an old compiler (6 years is almost an eternity) Commented Mar 30, 2012 at 22:01

4 Answers 4

43

Initialization had many limitations in the old C++. Your code is in fact not initializing anything at all; it's just calling a lot of member functions on an already initialized object.

In the current C++ (C++11) you can initialize your map properly:

std::map<std::string, std::vector<std::string>> const dict {
   { "USA", { "NYC", "LA", "Chicago" } },
   { "India", { "Delhi", "Bombay" }    }
};
Sign up to request clarification or add additional context in comments.

4 Comments

oh god, this is beautiful!
It is really too bad it took them ~15 years to come up with it :P
Oh, and OP said his compiler is g++ 3.4.6, which is very very far from C++11 - so posting elegant solutions that the OP can't use might not be that helpfull ... alas.
@haavee: I'm aware of that. There wasn't much to add to the OP's predicament, though.
9

If you're not opposed to using the Boost.Assign library and you are using C++ older than C++11, you can do it like this:

#include <boost/assign/list_of.hpp>
#include <boost/assign/std/vector.hpp>
#include <map>
#include <string>
#include <vector>

std::map<std::string, vector<std::string> > dict = boost::assign::map_list_of<std::string, std::vector<std::string> >
    ("USA",   boost::assign::list_of<std::string>("NYC")("LA")("Chicago")("Dallas"))
    ("India", boost::assign::list_of<std::string>("Delhi")("Bombay"))
;

Comments

8

If you're not afraid of using a bit of C-style macros and some helper constructs you might find this slightly less irritable; the initialization of the map is done in one line; you only need to fill in the data (which you must do anyway).

#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <utility>

using namespace std;

struct entry {
    string  key;
    string* vals;
    size_t  nvals;
};
#define NVAL(x) (sizeof(x)/sizeof(x[0]))

int main( void ) {
    // Create your data 
    string      usa[]      = {"NYC", "LA"};
    string      india[]    = {"Delhi", "Mumbai"};
    entry       dd[] = {
                          {"USA", usa, NVAL(usa)},
                          {"India", india, NVAL(india)}
                        };
    map<string, vector<string> > dict;

    // initialize the map
    for(unsigned int i=0; i<NVAL(dd); i++)
        dict.insert( make_pair(dd[i].key, vector<string>(dd[i].vals, dd[i].vals+dd[i].nvals)) );

    // Verify
    for( map<string,vector<string> >::const_iterator ptr=dict.begin();
         ptr!=dict.end(); ptr++) {
        cout << ptr->first << ": ";
        for( vector<string>::const_iterator eptr=ptr->second.begin();
             eptr!=ptr->second.end(); eptr++)
                cout << *eptr << " ";
        cout << endl;
    }
    return 0;
}

2 Comments

Your macro can be trivially replaced with a function template: template<typename T, std::size_t N> std::size_t NVAL(T (&)[N]) { return N; }.
That is indeed an elegant solution! Thx!
8

You could do this, if C++11 is not available:

map <string, vector<string> > dict;

string usa[] = { "NYC" , "LA" , "Chicago" , "Dallas" };
dict["USA"] = std::vector<string>(usa,usa+4);

Comments

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.