C Board  

Go Back   C Board > General Programming Boards > C++ Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 07-06-2007, 11:20 AM   #1
Registered User
 
Join Date: Nov 2006
Posts: 502
How to map enums to their string representation globaly?

Hi,

in my programs I often use enums for integer constants:

Code:
// directions.h

enum Directions
{
  west=1,
  south=2,
  east=3,
  nord=4
};
That .h file maybe gets includet in various .cpp files and the enum is used in different classes.
No I sometimes come to the point there I want to display the enum value, so I have to map them somewhere to their string representation.

best thing I came up with yet is to have a std::map<int, string> class memeber in each class what needs the enum-string-representation. the map is filled in the classes ctor.

now that's not a very clear solution because of the redundant code.

I wonder if their is a better solution to this problem or some well known idiom?

Thanks for your ideas!
pheres is offline   Reply With Quote
Old 07-06-2007, 11:22 AM   #2
Ethernal Noob
 
Join Date: Nov 2001
Posts: 1,888
either that or a switch case block.
indigo0086 is offline   Reply With Quote
Old 07-06-2007, 11:29 AM   #3
Massively Single Player
 
AverageSoftware's Avatar
 
Join Date: May 2007
Location: Buffalo, NY
Posts: 141
Make a map<Directions, string> that contains all the values, and then:

Code:
ostream &operator << (ostream &out, Directions d)
{
    out << DirectionMap[d];
    
    return out;
}
Something like this will allow you to directly print the string values, and adding a new direction is just a matter of adding it to the map.
__________________
There is no greater sign that a computing technology is worthless than the association of the word "solution" with it.
AverageSoftware is offline   Reply With Quote
Old 07-06-2007, 12:58 PM   #4
Tropical Coder
 
Darryl's Avatar
 
Join Date: Mar 2005
Location: Cayman Islands
Posts: 503
I think using a map is a bit overkill.

Here is what I typically do:
Code:
#include <iostream>
#include <string>

enum Directions
{
  west=1,
  south, // i removed the rest since it's sequential
  east,
  north, // changed spelling
};

std::string direction2string[] ={"","West", "South", "East", "North"}; // added dummy value to skip 0


int main ()
{     
     std::cout << direction2string[west] <<std::endl; 
     std::cout << direction2string[south] <<std::endl; 

}
__________________
SWinC - Simple Windows Class
Darryl is offline   Reply With Quote
Old 07-06-2007, 02:03 PM   #5
Registered User
 
Join Date: Nov 2006
Posts: 502
Thanks for you replies. But my question wasn't about the output in the first place (it's displayed in a gui most of the time).

the thing that bothers me is that the map<int, string> or the string array like in Darryls explanation has to be built in every single class what wants "to know" the string representation of the enum values. So if I have three classes I have 3 times the same bunch of code in the ctor. and if the enum changes, I have to change 3 classes. and if I forgot one, or switch the sequence of two enum values in one class by accident I run into trouble.

So I'm looking for a more central place to keep that string representation data. Sorry for making this not clear enough in my first post (I'm not a natural speaker).
pheres is offline   Reply With Quote
Old 07-06-2007, 02:19 PM   #6
Registered User
 
Join Date: Jan 2005
Posts: 7,137
I would make a header file with an enum and a global function declaration (perhaps in a namespace if you are using namespaces). The function would take the enum as a parameter and return a string. Then in a source file define the function to use your map or array or switch to return the proper string. If you use the map or array solution, define it in that source file in an unnamed namespace so it is local to that file.

This way the other code can use the enum and call the function, yet all that code will be written and maintained in one place.
Daved is offline   Reply With Quote
Old 07-06-2007, 02:22 PM   #7
C++ Witch
 
laserlight's Avatar
 
Join Date: Oct 2003
Location: Singapore
Posts: 10,365
In Effective C++, Third Edition, Item 18, Scott Meyers suggests creating a full fledged class for a case that seems like the one you are facing. A possible adaptation of his suggestion would be:
Code:
class Direction
{
public:
    static Direction west()
    {
        return Direction(1);
    }
    static Direction south()
    {
        return Direction(2);
    }
    static Direction east()
    {
        return Direction(3);
    }
    static Direction north()
    {
        return Direction(4);
    }

    // ... other member functions ...

private:
    // prevent creation of new Direction values
    explicit Direction(int d) : direction(d) {}
    // Direction specific data
    int direction;
};
In this case, the class would pretty much be global, but rather safely so.
__________________
C + C++ Compiler: MinGW port of GCC
Build + Version Control System: SCons + Bazaar

Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
laserlight is online now   Reply With Quote
Old 07-06-2007, 02:39 PM   #8
Tropical Coder
 
Darryl's Avatar
 
Join Date: Mar 2005
Location: Cayman Islands
Posts: 503
Quote:
Originally Posted by pheres View Post
Thanks for you replies. But my question wasn't about the output in the first place (it's displayed in a gui most of the time).

the thing that bothers me is that the map<int, string> or the string array like in Darryls explanation has to be built in every single class what wants "to know" the string representation of the enum values. So if I have three classes I have 3 times the same bunch of code in the ctor. and if the enum changes, I have to change 3 classes. and if I forgot one, or switch the sequence of two enum values in one class by accident I run into trouble.

So I'm looking for a more central place to keep that string representation data. Sorry for making this not clear enough in my first post (I'm not a natural speaker).
What ever container holds the strings, map in your case or the array in mine can be used in another file with extern, just as you would any other global variable.

**EDIT**
Just looking at Daved's post, take my direction2string, wrap it in a function with the protype in the header

Code:
In your header 
direction.h
enum Directions
{
  west=1,
  south=2,
  east=3,
  nord=4
};

std::string dir2str(Directions d);

in your implementation
direction.cpp

std::string dir2str(Directions d)
{
     std::string direction2string[] ={"","West", "South", "East", "North"};
     return direction2string[d];
}
Now you just include the header and call wherever needed
__________________
SWinC - Simple Windows Class

Last edited by Darryl; 07-06-2007 at 02:57 PM. Reason: Read Daved's post
Darryl is offline   Reply With Quote
Old 07-06-2007, 02:57 PM   #9
C++ Witch
 
laserlight's Avatar
 
Join Date: Oct 2003
Location: Singapore
Posts: 10,365
Actually, is there any good reason to start the numbering from 1 instead of 0 for the case of the enum? Even in my suggested solution the actual values of the numbers do not really matter, and starting from 0 will make using an array of names easier. The downside to using an enum as opposed to a class is that it is less typesafe, methinks.
__________________
C + C++ Compiler: MinGW port of GCC
Build + Version Control System: SCons + Bazaar

Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
laserlight is online now   Reply With Quote
Old 07-06-2007, 03:12 PM   #10
Tropical Coder
 
Darryl's Avatar
 
Join Date: Mar 2005
Location: Cayman Islands
Posts: 503
Quote:
Originally Posted by laserlight View Post
The downside to using an enum as opposed to a class is that it is less typesafe, methinks.
I don't think it's any less typesafe than a class and possibly more, because the values are constants.
__________________
SWinC - Simple Windows Class
Darryl is offline   Reply With Quote
Old 07-07-2007, 09:33 AM   #11
C++ Witch
 
laserlight's Avatar
 
Join Date: Oct 2003
Location: Singapore
Posts: 10,365
Quote:
I don't think it's any less typesafe than a class and possibly more, because the values are constants.
The use of (static) member functions as opposed to objects to represent the values means that the 'values' are effectively constants too.

What I had in mind was more of the
Code:
int s = south;
kind of thing, though I suppose it is not particularly likely to happen by mistake.
__________________
C + C++ Compiler: MinGW port of GCC
Build + Version Control System: SCons + Bazaar

Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
laserlight is online now   Reply With Quote
Old 07-07-2007, 10:26 AM   #12
l'Anziano
 
DavidP's Avatar
 
Join Date: Aug 2001
Posts: 2,573
Basically I kind of echo what laserlight has been saying. Make a class, and then that class may be used by any other class in your project.

Even if you don't want to make it an entire class, I would still take that code out and put it in a separate "common" header file that all your classes have access to. Most projects usually have some type of file called "common.h" or "shared.h" which is just a file that has tons of stuff in it that everything wants to use.

By the way, I noticed that in your first post, you spelled "north" as "nord". What country do you come from? sei italiano?
__________________
My Website

"Circular logic is good because it is."
DavidP is offline   Reply With Quote
Old 07-07-2007, 10:37 PM   #13
CSharpener
 
vart's Avatar
 
Join Date: Oct 2006
Posts: 5,242
And you class may also want to load strings from resources - so it will be easier later to switch to another language
__________________
If I have eight hours for cutting wood, I spend six sharpening my axe.
vart is offline   Reply With Quote
Old 07-08-2007, 02:28 AM   #14
Registered User
 
Join Date: Nov 2006
Posts: 502
Thank you all for that inspiring discussion!

That are two very reasonable solutions so far. I'm still not shure what to prefer: laserlights class with the static functions or Darryls global function. I'll probably try the class, because there I have to "touch" every value only one time.
Thing is I have some enums here with more than 100 values in it. So I better write a converter program. finally a reason to learn about boost::regex

two questions remains to me. first

Code:
std::string dir2str(Directions d)
{
     std::string direction2string[] ={"","West", "South", "East", "North"};
     return direction2string[d];
}
If I would want to use a std::map instead of the array, could it also be initialized in a similar fashion like the array above?
Code:
     std::map<int,string> directions = . . .  ;
Second: what's the thing with the "load strings from resources"? I know that the microsoft c++ compiler use resource files and in wxwidgets I've seen that too. But are there some portable resource files? Or do you just mean to read the strings from a file with a format I choose?


"nord" comes more from the country in the north of italy
pheres is offline   Reply With Quote
Old 07-08-2007, 09:20 AM   #15
Tropical Coder
 
Darryl's Avatar
 
Join Date: Mar 2005
Location: Cayman Islands
Posts: 503
1st - No you can't initialize maps with an initialization list. As a matter of fact, you can't with any of the standard template containers which is an issue I think they are addressing in the new standard.

Now, here's my arguements for enums.

1. Ease of implemenation - You'd have to write a function for each "value" you want which as you've already stated, with hundreds could be a lot.

2. Maintenance and error proneness. - Because you have to assign each integer value, a class with hundreds of values is more prone to duplicates, either by careless assignment or typo whereas enum value assignment is automatic. Inserting a value in between other values would be quite difficult for the static functions.

3. Efficiency - Every time you change a direction, with the static method you create a new temp object which calls a constructor, destructor and assignment operator.

That's all I can think of now. :-)
__________________
SWinC - Simple Windows Class

Last edited by Darryl; 07-08-2007 at 09:22 AM.
Darryl is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
String, Pair and Map Problem dream_noir C++ Programming 3 02-19-2009 07:46 PM
String Class BKurosawa C++ Programming 117 08-09-2007 01:02 AM
We Got _DEBUG Errors Tonto Windows Programming 5 12-22-2006 05:45 PM
Message class ** Need help befor 12am tonight** TransformedBG C++ Programming 1 11-29-2006 11:03 PM
can anyone see anything wrong with this code occ0708 C++ Programming 6 12-07-2004 12:47 PM


All times are GMT -6. The time now is 08:16 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22