Seeking code for temple for a <map> of enum to string

Discussion in 'C++' started by Baron Samedi, Mar 16, 2009.

  1. Baron Samedi

    Baron Samedi Guest

    I know that it's an old one - how to take an enum value and output a
    string.

    I'd like to make it a template class, so that I can add to it in a
    general manner.

    I would also like to be able to extend it later.

    I am stumped!!

    Any ideas?

    Thanks in advance for any help
    Baron Samedi, Mar 16, 2009
    #1
    1. Advertising

  2. Baron Samedi

    SG Guest

    On 16 Mrz., 04:04, Baron Samedi <> wrote:
    > I know that it's an old one - how to take an enum value and output a
    > string.


    ....with a std::map you mean? Well, it's not that hard.

    > I'd like to make it a template class, so that I can add to it in a
    > general manner.


    Huh? "make it a template class"? You don't need to write another
    implementation. Just use the one provided in the header <map>

    > I would also like to be able to extend it later.


    Extend WHAT and HOW?

    > I am stumped!!
    > Any ideas?


    Did you even attempt to solve your problem on your own? At least query
    a search engine or Wikipedia or something.

    Cheers!
    SG
    SG, Mar 16, 2009
    #2
    1. Advertising

  3. Baron Samedi

    James Kanze Guest

    On Mar 16, 4:04 am, Baron Samedi <> wrote:
    > I know that it's an old one - how to take an enum value and
    > output a string.


    I'm assuming that you also want some relationship between the
    enum value and the string. And that you want the string to be
    generated automatically, mapped from the name of the enum value.

    For that, you need either a compiler extension or some external
    program which reads your source and generates the necessary
    mappings.

    > I'd like to make it a template class, so that I can add to it
    > in a general manner.


    A template can't deal with the names of things.

    --
    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, Mar 16, 2009
    #3
  4. Baron Samedi

    Guest

    On 16 Mar, 03:04, Baron Samedi <> wrote:

    > I know that it's an old one - how to take an enum value and output a
    > string.
    >
    > I'd like to make it a template class, so that I can add to it in a
    > general manner.
    >
    > I would also like to be able to extend it later.
    >
    > I am stumped!!
    >
    > Any ideas?


    I've only seen this done with a code generator. In the case I saw,
    Rational Rose.
    I was never impressed with the way it actually worked and always meant
    to
    invent a better one. A code generator shouldn't be too dificult to
    write
    though.
    , Mar 16, 2009
    #4
  5. Baron Samedi

    Jorgen Grahn Guest

    On Sun, 15 Mar 2009 20:04:33 -0700 (PDT), Baron Samedi <> wrote:
    > I know that it's an old one - how to take an enum value and output a
    > string.
    >
    > I'd like to make it a template class, so that I can add to it in a
    > general manner.
    >
    > I would also like to be able to extend it later.


    Is this enough? If not, why?

    enum Foo { Bar, Baz, ... };

    std::eek:stream& operator<< (std::eek:stream& os, const Foo& val)
    {
    switch(val) {
    case Bar: return os << "Bar";
    case Baz: return os << "Baz";
    ...
    }
    }

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Ph'nglui mglw'nafh Cthulhu
    \X/ snipabacken.se> R'lyeh wgah'nagl fhtagn!
    Jorgen Grahn, Mar 16, 2009
    #5
  6. Baron Samedi

    Guest

    On Mar 15, 11:04 pm, Baron Samedi <> wrote:
    > I know that it's an old one - how to take an enum value and output astring.
    >
    > I'd like to make it a template class, so that I can add to it in a
    > general manner.
    >
    > I would also like to be able to extend it later.
    >
    > I am stumped!!
    >
    > Any ideas?
    >
    > Thanks in advance for any help


    This is a common task. Of course, inside you program, library, or
    collection of libraries you want to just use your enumerator. But
    what you've defined as an enumerator may come in from the external
    world as text.

    Textual representation also comes in handy for error messages and when
    serializing data. Serializing an enumerator as an int is a future
    maintenance nightmare just waiting to happen. Doing so means you
    can't change the value of an emuerator without worrying about breaking
    something.

    What we have done is implement three template functions for each
    enumerator.
    Here are their signatures:

    // convert a string to an enumerator - throw an exception if the
    string is invalid
    template <class T>
    T stringToEnum (const std::string & s)

    // convert a string to an enumerator
    // on success, return true and set t; on failure, return false and t
    is not touched
    template <class T>
    bool stringToEnum (const std::string & s, T & t)

    // convert an enumerator to string (actually const char *)
    template <class T>
    const char * enumToSTring (T t);

    Internally these are implemented using a static array of pairs of
    const char * and enumerators. Using a static array of POD means there
    are no of order of initialization or thread safety issues that you
    might encounter using a std::map (for instance) or other C++ class.

    Lookup is done using linear search. We've never had any performance
    issues with this. When converting from string to enumerator we use
    case insensitive compares. Different strings can be mapped to the
    same enumerator value if needed. When converting from enumerator to
    string the first entry in the array will be the "preferred" text
    representation.

    What's more, we've hidden all of the implementation by explicitly
    instantiating each function inside the implementation file. The user
    of the functions never see anything but the plain old enumerator and
    the signature of the above classes.

    These functions go a long way to solving the enumerator to string and
    string to enumerator task. With them, writing an operator<< or
    operator>> is trivial.

    The code is done at work - I will ask if it is ok to post it.

    HTH
    , Mar 29, 2009
    #6
  7. Baron Samedi

    James Kanze Guest

    On Mar 29, 10:18 pm, "" <>
    wrote:
    > On Mar 15, 11:04 pm, Baron Samedi <> wrote:


    > > I know that it's an old one - how to take an enum value and
    > > output astring.


    > > I'd like to make it a template class, so that I can add to it in a
    > > general manner.


    > This is a common task. Of course, inside you program,
    > library, or collection of libraries you want to just use your
    > enumerator. But what you've defined as an enumerator may come
    > in from the external world as text.


    > Textual representation also comes in handy for error messages
    > and when serializing data. Serializing an enumerator as an int
    > is a future maintenance nightmare just waiting to happen.
    > Doing so means you can't change the value of an emuerator
    > without worrying about breaking something.


    Well, the obvious answer to that is "don't change them":).
    Seriously, you do need some sort of versioning, even if you're
    using text represtations for serialization, since you have to
    deal with enum values being added and removed. (Of course, all
    of the other arguments for textual representation still hold.
    Reading "operationPending" for the state, rather than "5", makes
    debugging considerably easier.)

    > What we have done is implement three template functions for each
    > enumerator.
    > Here are their signatures:


    > // convert a string to an enumerator - throw an exception if the
    > string is invalid
    > template <class T>
    > T stringToEnum (const std::string & s)


    > // convert a string to an enumerator
    > // on success, return true and set t; on failure, return false and t
    > is not touched
    > template <class T>
    > bool stringToEnum (const std::string & s, T & t)


    > // convert an enumerator to string (actually const char *)
    > template <class T>
    > const char * enumToSTring (T t);


    Just a question: you have generic templates to do this? I can't
    see how (but maybe I've missed something).

    In my case, I use a (originally) simple program, capable of
    understanding enough C++ to parse the enums, to generate the
    implementations of these. Also, I've found that the template
    solution poses some problems, mainly with regards to namespaces;
    my solution has been to generate functions toString( EnumType )
    and to<EnumType>( string ). And a third, fromString( string,
    EnumType& ) for use in templates. (Having the EnumType in an
    argument makes the function name dependent, and causes ADL to
    kick in.) These functions are generated in the same namespace
    as the enum.

    I originally used the template approach, but couldn't find an
    appropriate namespace to put it in. (More exactly, I orginally
    implemented the code as part of my library, with the templates
    in the same namespace as the library code. This version is
    available at my site: http://kanze.james.neuf.fr/code-en.fr. I
    have since changed the implementation to remove all dependencies
    on my library in the generated code. Having done this, I didn't
    want it to use the namespace Gabi, and I couldn't find another
    appropriate namespace for the templates. I actually liked the
    idea of naming the function templates string_cast, and putting
    them in global namespace, but I was too worried about possible
    conflicts with other code.)

    FWIW, the current implementation has options to generate either:
    Gabi::Util::Fallible< std::string > toString( enum_type ) ;
    Gabi::Util::Fallible< enum_type > toenum_type( std::string
    const& ) ;
    bool fromString( enum_type&, std::string const& ) ;
    (for myself and others using my library) or
    char const* toString( enum_type ) ;
    enum_type const* toenum_type( std::string const& ) ;
    bool fromString( enum_type&, std::string const& ) ;
    (With enum_type being the type of the enum, of course). When
    all is said and done, however, I think that in this case, using
    Fallible instead of pointers may be overkill.

    > Internally these are implemented using a static array of pairs
    > of const char * and enumerators. Using a static array of POD
    > means there are no of order of initialization or thread safety
    > issues that you might encounter using a std::map (for
    > instance) or other C++ class.


    Agreed. At one point, I toyed with the idea of having two
    std::map at the interface level, so that users would have a well
    known interface to deal with, rather than something I define
    myself. In the end, both order of initialization and naming
    problems lead me to abandon this approach.

    > Lookup is done using linear search. We've never had any
    > performance issues with this. When converting from string to
    > enumerator we use case insensitive compares.


    That's an interesting idea. Sounds like I'll have to add an
    option to my generator.

    > Different strings can be mapped to the same enumerator value
    > if needed.


    And different enumerators to the same string?

    > When converting from enumerator to string the first entry in
    > the array will be the "preferred" text representation.


    I do a one to one mapping, but at the symbolic level (name
    to/from string); if two enum constants have the same value, then
    I handle it as you do---first match is used.

    I also permit (in the current versions) transformations in the
    name, mainly because I had code available which supported this
    already, and I've encountered places which had special naming
    conventions for enum constants, that you possibly wouldn't want
    to appear in the external representations.

    > What's more, we've hidden all of the implementation by
    > explicitly instantiating each function inside the
    > implementation file. The user of the functions never see
    > anything but the plain old enumerator and the signature of the
    > above classes.


    So you do have an explicit specialization for each enum. Hand
    written, or automatically generated?

    Note that for the code to be conform, you do need for a
    declaration of the specification to be visible anytime it is
    used.

    > These functions go a long way to solving the enumerator to
    > string and string to enumerator task. With them, writing an
    > operator<< or operator>> is trivial.


    > The code is done at work - I will ask if it is ok to post it.


    But the code is probably simpler than defining the interface:).
    A simple struct, a couple of predicates, and std::find_if should
    do the trick.

    --
    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, Mar 30, 2009
    #7
  8. On Mar 15, 10:04 pm, Baron Samedi <> wrote:
    > I know that it's an old one - how to take an enum value and output a
    > string.
    >
    > I'd like to make it a template class, so that I can add to it in a
    > general manner.
    >
    > I would also like to be able to extend it later.
    >
    > I am stumped!!
    >
    > Any ideas?
    >
    > Thanks in advance for any help



    Paul Hsieh (a regular in c.l.c) used preprocessor tricks to do what
    you are after:

    http://www.azillionmonkeys.com/qed/einst.c

    (look at decls)

    hope this helps,
    - Anand
    Anand Hariharan, Mar 30, 2009
    #8
    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. O'Neal Computer Programmer

    python scripting game The Temple Of Elemental Evil update

    O'Neal Computer Programmer, Jul 7, 2003, in forum: Python
    Replies:
    1
    Views:
    410
    Bengt Richter
    Jul 7, 2003
  2. O'Neal Computer Programmer

    Temple of Elemental Evil and Python

    O'Neal Computer Programmer, Oct 30, 2003, in forum: Python
    Replies:
    0
    Views:
    572
    O'Neal Computer Programmer
    Oct 30, 2003
  3. albert kao
    Replies:
    12
    Views:
    583
    Roedy Green
    Oct 7, 2011
  4. Nish

    How to implemet the same code in temple column(text box)

    Nish, Jul 2, 2004, in forum: ASP .Net Datagrid Control
    Replies:
    2
    Views:
    118
  5. Trevor Turk

    Ruby, Debian, and Media Temple

    Trevor Turk, Dec 18, 2006, in forum: Ruby
    Replies:
    5
    Views:
    115
    Eric Hodel
    Dec 19, 2006
Loading...

Share This Page