Initialising a map

A

Angus

Should I be able to do something like this:

static const std::map<RequestType, string> RequestMap = {
{ AOpenEx, "AOpenEx" },
{ AClose, "AClose" },
{ ARegister, "ARegister" },
{ AUnregister, "Unregister" } };

RequestType is an enum.

I can't compile it. Or can I not initialise with an array like this?
 
D

David Côme

Should I be able to do something like this:

static const std::map<RequestType, string> RequestMap = {
{ AOpenEx, "AOpenEx" },
{ AClose, "AClose" },
{ ARegister, "ARegister" },
{ AUnregister, "Unregister" } };

RequestType is an enum.

I can't compile it. Or can I not initialise with an array like this?


look at boost::assign and particularly at map_list_of
 
A

Angus

look at boost::assign and particularly at map_list_of

Unfortunately I cannot use boost here. Maybe it is easier not to use
a map as the data is fairly static. What is the easiest way for me to
create a mapping like this?
 
R

rep_movsd

Unfortunately I cannot use boost here.  Maybe it is easier not to use
a map as the data is fairly static.  What is the easiest way for me to
create a mapping like this?

Maybe use a loop?

RequestType keys[] = {AOpenEx, AClose, ARegister, AUnregister,};
const char* vals[] = {"AOpenEx", "AClose", "ARegister",
"AUnregister"};

std::map<RequestType, string> myMap;
for(int n = 0; n < (sizeof(keys) / sizeof(keys[0])); ++n)
{
myMap[keys[n]] = vals[n];
}

....

If you are always going to have the string exactly the same as
RequestType enum and you have a large number of such, maybe you can do
some preprocessor stuff, this will avoid any errors while typing.

Vivek
 
S

SeanW

Unfortunately I cannot use boost here. Maybe it is easier not to use
a map as the data is fairly static. What is the easiest way for me to
create a mapping like this?

How about:

typedef std::map<RequestType, string> RequestMap;
RequestMap tmp_map;
tmp_map[AOpenEx] = "AOpenEx";
tmp_map[AClose] = "AClose";
tmp_map[ARegister] = "ARegister";
tmp_map[AUnregister] = "AUnregister";
static const RequestMap const_map(tmp_map);

A bit ugly, but it works.

You might also be interested in this proposal for future
C++ initializer lists:

http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1509.pdf


Sean
 
A

AnonMail2005

Should I be able to do something like this:

  static const std::map<RequestType, string> RequestMap = {
    { AOpenEx,                    "AOpenEx" },
    { AClose,                     "AClose" },
    { ARegister,                 "ARegister" },
    { AUnregister,               "Unregister" } };

RequestType is an enum.

I can't compile it.  Or can I not initialise with an array like this?
If your map contents won't change much in the future, just initialize
it
from two arrays or an array of POD structs.

If the map will be added to in the future, you may want to look into
having a register function. See Modern C++ Design for how to do this.
In that book, he used this technique to register names/creation
function pointers with a factory.

HTH
 
T

tragomaskhalos

Should I be able to do something like this:

  static const std::map<RequestType, string> RequestMap = {
    { AOpenEx,                    "AOpenEx" },
    { AClose,                     "AClose" },
    { ARegister,                 "ARegister" },
    { AUnregister,               "Unregister" } };

RequestType is an enum.

Check this out (a previous thread on the same question):
http://groups.google.com/group/comp.lang.c++/browse_thread/thread/8fa984af51eba51a
 
J

Juha Nieminen

Angus said:
static const std::map<RequestType, string> RequestMap = {
{ AOpenEx, "AOpenEx" },
{ AClose, "AClose" },
{ ARegister, "ARegister" },
{ AUnregister, "Unregister" } };

Followup question: Will this be possible with the upcoming C++
standard? (AFAIK something similar will be possible with std::vector.)
 
J

James Kanze

Should I be able to do something like this:
static const std::map<RequestType, string> RequestMap = {
{ AOpenEx, "AOpenEx" },
{ AClose, "AClose" },
{ ARegister, "ARegister" },
{ AUnregister, "Unregister" } };
RequestType is an enum.
I can't compile it. Or can I not initialise with an array
like this?

You can initialize it with an array. You can't use agglomerate
initialization on it, however, because it isn't an agglomerate.

The general solution is to declare something like:

typedef std::map< RequestType, string >
RequestMap ;

struct RequestMapInitializer
{
RequestType key ;
char const* value ;
operator RequestMap::value_type() const
{
return RequestMap::value_type(
key, std::string( value ) ;
}
}
RequestMapInitializer const initializer[] =
{
{ AOpenEx , "AOpenEx" },
{ AClose , "AClose" },
{ ARegister , "ARegister" },
{ AUnregister, "Unregister" },
}

RequestMap requestMap( begin( initializer ),
end( initializer ) ) ;

(with the usual definitions for begin and end, of course).

For small things like this, I find just using a C style array
and std::find simpler, and perfectly adequate. So I wrote a
template class StaticMap

template< typename MappedType,
typename KeyType = char const* >
struct StaticMap
{
KeyType key ;
MappedType value ;

class Matcher
{
public:
explicit Matcher( KeyType const& targetKey )
: myKey( targetKey )
{
}

bool operator()( StaticMap const& obj )
const
{
return myKey == obj.key ;
}

private:
KeyType myKey ;
} ;

static StaticMap const*
find(
StaticMap const* begin,
StaticMap const* end,
KeyType const& value )
{
return std::find_if( begin, end, Matcher( value ) ) ;
}
} ;

(Originally, the key type was always char const*, since that
corresponded to most of my uses. That's why it's unexpectedly
the second template argument.)
 
J

jl_post

Should I be able to do something like this:

static const std::map<RequestType, string> RequestMap = {
{ AOpenEx, "AOpenEx" },
{ AClose, "AClose" },
{ ARegister, "ARegister" },
{ AUnregister, "Unregister" } };

RequestType is an enum.

I can't compile it. Or can I not initialise with an array like this?


To be honest, I don't know of a simple way to do what you want
using both "const" and a non-pointer. But if you don't mind using a
const pointer, you can do it this way:


#include <iostream>
#include <map>
#include <string>

enum RequestType
{
AOpenEx,
AClose,
ARegister,
AUnregister
};

int main(int argc, char ** argv)
{
static const std::map<RequestType,std::string> * RequestMap = NULL;
if (!RequestMap)
{
static std::map<RequestType,std::string> tmpMap;
tmpMap[AOpenEx] = "AOpenEx";
tmpMap[AClose] = "AClose";
tmpMap[ARegister] = "ARegister";
tmpMap[AUnregister] = "AUnregister";

RequestMap = &tmpMap;
}

std::map<RequestType,std::string>::const_iterator it
= RequestMap->find(AOpenEx);
std::cout << "RequestMap[AOpenEx] = \""
<< it->second << '"'
<< std::endl;

// This next line shouldn't compile (due to "const"):
// (*RequestMap)[AOpenEx] = "blah";

return 0;
}


This approach requires you to use RequestMap as a pointer, which
might make your syntax a little messier.

But if you'd rather not use a pointer (and are fine with not using
"const"), you might prefer this next approach:


#include <iostream>
#include <map>
#include <string>

enum RequestType
{
AOpenEx,
AClose,
ARegister,
AUnregister
};

int main(int argc, char ** argv)
{
static std::map<RequestType,std::string> RequestMap;
if (RequestMap.empty())
{
RequestMap[AOpenEx] = "AOpenEx";
RequestMap[AClose] = "AClose";
RequestMap[ARegister] = "ARegister";
RequestMap[AUnregister] = "AUnregister";
}

std::cout << "RequestMap[AOpenEx] = \""
<< RequestMap[AOpenEx] << '"'
<< std::endl;

// Unfortunately, this next line DOES compile:
RequestMap[AOpenEx] = "blah";

return 0;
}


The syntax in the second approach is simpler, I think. However,
this approach suffers from the fact that RequestMap is not declared
"const", so it can be freely populated/modified, which is probably not
what you want.

However, both approaches benefit from the fact that RequestMap is
only populated once no matter how many times the function it is in is
called.

I hope this helps, Angus.

-- Jean-Luc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top