Re: Initializing a map...
On Feb 21, 1:22 am, Jeff Schwab <j...@schwabcenter.com> wrote:
barcaroller wrote:
Is there a way in C++ to initialize an STL map in one
statement (the way arrays can be initialized in C)?
For example, instead of using:
map<type1,type2> mymap;
mymap[key1] = value1;
mymap[key2] = value2;
I would like to use something like:
// wrong syntax!
map<type1,type2> mymap = { (key1, value1), (key2, value2) };
There's no special syntax for maps.
I think there will be in the next version of the standard. (I
know that there was a proposal for extended initializers, but
I'm not sure what the current status of the proposal was.)
You do have a few options, though.
One is to initialize an array with the nicer syntax, then initialize
the map from the array.
This is the only way to create a const map.
typedef std::map<type1, type2> map_type;
typedef map_type::value_type pair_type;
template<typename T, std::size_t z>
std::size_t size(T const (&a)[z]) {
return z;
}
int main() {
pair_type initializers[] =
{ pair_type(key1, value1), pair_type(key2, value2) };
map_type m(initializers, initializers + size(initializers));
}
I often find it worthwhile to define a special structure for
this, something along the lines of:
typedef std::map< std::string, double > Map ;
struct MapInit
{
char const* key ;
double value ;
operator Map::value_type() const
{
return Map::value_type( std::string( key ), value ) ;
}
} ;
Partially for historical reasons: earlier Microsoft compilers
had problems with agglomerate initialization if the components
of the agglomerate weren't agglomerates themselves. But having
gotten into the habit of it... It's still worth considering if
the initialization array is in a separate compilation unit (e.g.
because it is machine generated), since you can arrange for the
table of MapInit to use static initialization, thus avoiding all
order of initialization issues.
Another option is to create the map within a function, then
return it by value.
map_type create_map() {
map_type result;
result.insert(pair_type(key1, value1));
result.insert(pair_type(key2, value2));
return result;
}
int main() {
map_type map = create_map();
}
Not recommended for big maps in the middle of a tight loop:-).
A third option is to let the map start out empty, then use a
function to populate it.
void populate(map_type& m) {
m.insert(pair_type(key1, value1));
m.insert(pair_type(key2, value2));
}
int main() {
map_type m;
populate(m);
}
Neither of the above allow the map to be const, of course.
Another possibility is to derive, with the derived class
providing a constructor which populates the map (and nothing
else). Again, this allows the map to be const. It also works
with older implementations, which didn't always support the two
iterator form of the constructor (because they were designed
around compilers which didn't support member templates). So you
have something like:
class MyMap : public std::map< type1, type2 >
{
public:
MyMap() ;
} ;
MyMap::MyMap()
{
insert( value_type( key1, value1 ) ) ;
insert( value_type( key2, value2 ) ) ;
// ...
}
(Again, you could probably arrange for the constructor to be
machine generated.)
Concerning the "machine generated": if your map has so few
entries that you can consider writing them out by hand, you're
likely better off just using a C style array and std::find_if.
(For a const map, of course. But I can't remember a case where
I wanted to initialize the map's contents on creation, but
didn't want it const, although I'm sure that they do exist.)
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34