Initialising a map

Discussion in 'C++' started by Angus, Jun 27, 2008.

  1. Angus

    Angus Guest

    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?
     
    Angus, Jun 27, 2008
    #1
    1. Advertising

  2. On Fri, 27 Jun 2008 15:06:09 +0200, Angus <> wrote:

    > 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
     
    David Côme, Jun 27, 2008
    #2
    1. Advertising

  3. Angus

    Angus Guest

    On 27 Jun, 14:13, David Côme <> wrote:
    > On Fri, 27 Jun 2008 15:06:09 +0200, Angus <> wrote:
    > > 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


    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?
     
    Angus, Jun 27, 2008
    #3
  4. Angus

    rep_movsd Guest

    On Jun 27, 4:30 pm, Angus <> wrote:
    > On 27 Jun, 14:13, David Côme <> wrote:
    >
    > > On Fri, 27 Jun 2008 15:06:09 +0200, Angus <> wrote:
    > > > 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

    >
    > 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
     
    rep_movsd, Jun 27, 2008
    #4
  5. Angus

    SeanW Guest

    On Jun 27, 9:30 am, Angus <> wrote:
    > On 27 Jun, 14:13, David Côme <> wrote:
    >
    > > On Fri, 27 Jun 2008 15:06:09 +0200, Angus <> wrote:
    > > > 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

    >
    > 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
     
    SeanW, Jun 27, 2008
    #5
  6. Angus

    Guest

    On Jun 27, 9:06 am, Angus <> wrote:
    > 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
     
    , Jun 27, 2008
    #6
  7. On Jun 27, 2:06 pm, Angus <> wrote:
    > 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
     
    tragomaskhalos, Jun 27, 2008
    #7
  8. Angus wrote:
    > 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.)
     
    Juha Nieminen, Jun 27, 2008
    #8
  9. Angus

    James Kanze Guest

    On Jun 27, 3:06 pm, Angus <> wrote:
    > 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.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jun 27, 2008
    #9
  10. Angus

    Guest

    On Jun 27, 7:06 am, Angus <> wrote:
    > 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
     
    , Jun 27, 2008
    #10
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. jan

    Initialising a signal

    jan, Dec 16, 2003, in forum: VHDL
    Replies:
    3
    Views:
    497
    David Jones
    Dec 23, 2003
  2. Jo Inferis
    Replies:
    0
    Views:
    391
    Jo Inferis
    Jun 20, 2004
  3. Phil Winstanley [Microsoft MVP ASP.NET]

    Re: Dynamic user control loading/initialising

    Phil Winstanley [Microsoft MVP ASP.NET], Jun 20, 2004, in forum: ASP .Net
    Replies:
    2
    Views:
    396
    Jo Inferis
    Jun 20, 2004
  4. Dave

    Initialising UserControls

    Dave, Sep 3, 2004, in forum: ASP .Net
    Replies:
    2
    Views:
    317
    Justin Beckwith
    Sep 3, 2004
  5. Paul Brettschneider

    Initialising map member without copy

    Paul Brettschneider, Mar 1, 2008, in forum: C++
    Replies:
    23
    Views:
    812
    Paul Brettschneider
    Mar 5, 2008
Loading...

Share This Page