Hello all.
Is it possible to convert an enum member variable to a string?
This would be useful in some cases...
Printable View
Hello all.
Is it possible to convert an enum member variable to a string?
This would be useful in some cases...
If you are sufficiently bored, you can write a function that accepts an enum as an argument and returns a string. But there is no default conversion.
If you are looking to get the text names in an enum (these are used a lot for errors, etc), you can write a function with a switch/case inside based on the enum, that returns a string.
It is very often useful. I use a short perl script that you can feed the enum source code into and have it spit out a switch case in C based on the values. They can be very long, that saves much copy pasting.
Yeah, no simple way to have it.
But on the sunny side, you can overload operator<< for the enum :)
Side question: doesn't the standard say that any two enum values ORed together are also valid values for the enum variable (e.g when used as bitfields)?Code:#include <iostream>
#include <cassert>
enum X { a, b };
std::ostream& operator<<(std::ostream& os, X x)
{
switch (x) {
case a: return os << "a";
case b: return os << "b";
}
assert(false && "wrong enum value");
}
int main()
{
X x = a;
std::cout << a;
}
Thanks for the replies.
Yes, I was looking for a way to get the string names of the member variables of an enum. I was hoping that there was a function generic enough to accept any enum, and return the text name of any given variable of the enum. Of course I had already considered writing a function for handling specifically the enum I want to do this with (the code would be easy enough), but I was hoping for a function which could handle any enum. I guess that's not possible though.
Yes, that would be certainly useful. Any chance you would let me have the source code of that perl script?Quote:
It is very often useful. I use a short perl script that you can feed the enum source code into and have it spit out a switch case in C based on the values. They can be very long, that saves much copy pasting.
I really wish we could do this in C++ as it is useful in a lot of situations. This is one thing, IMO, that is lacking from the language - but if you could convert enums to strings it might introduce other issues related to using enumerations that I can't think of off the top of my head. ORing certainly would be one of them.
Hmm...I'm thinking I might be able to write a simple C++ program which can open a .cpp or .h file, read it line by line, checking each for an string 'enum'. And each time it finds it, it will read every line (parsing the string to include only the names of the enum values, instead of also the '=' sign and the number values), until it finds the terminating semicolon following. Each enum value name will be stored in a separate string (probably in an array).
It will then write a function for retrieving one of those string values from the array (using an exact copy of the original enum as a paramater argument). When the user wants to retrieve a specific enumeration value from this function, he will simply call it up, passing in the name of the enumeration value he wants to retrieve as a string.
The code that the program will write to file for each enum will look something like this:
Then the user can simply include the generated header file in his or hers source file, and call the function as needed.Code:class CNameOfEnumToString {
public:
CNameOfEnumToString();
const char getStringOfEnumValueX(NameOfEnum enumVar);
enum NameOfEnum {
NameOfEnumValue1,
NameOfEnumValue2,
NameOfEnumValue3
};
private:
const char NameOfArrayForHoldingEnumValues[];
};
CenumToString::CenumToString() {
NameOfArrayForHoldingEnumValues[0] = "NameOfEnumValue1";
NameOfArrayForHoldingEnumValues[1] = "NameOfEnumValue2";
NameOfArrayForHoldingEnumValues[2] = "NameOfEnumValue3";
}
const char CenumToString::getStringOfEnumValueX(NameOfEnum enumVar) {
if (enumVar == NameOfEnumValue1) {
return NameOfArrayForHoldingEnumValues[0];
}
if (enumVar == NameOfEnumValue2) {
return NameOfArrayForHoldingEnumValues[1];
}
if (enumVar == NameOfEnumValue3) {
return NameOfArrayForHoldingEnumValues[2];
}
}
The standard says:
(Note 4 gives details about 1's and 2's complement values.)Quote:
For an enumeration where emin is the smallest enumerator and emax is the largest, the values of the enumeration are the values of the underlying type in the range bmin to bmax, where bmin and bmax are, respectively, the smallest and largest values of the smallest bitfield that can store emin and emax.4) It is possible to define an enumeration that has values not defined by any of its enumerators.
I take it mean that the following is guaranteed to work (with respect to the underlying type and all):
Depending on whether it makes sense for a particular enum or not (it does for X), you'd also need to be able to handle this. Should be perfectly possible to handle, except not with a switch (e.g the string representation could be "b | c").Code:enum X {a =1, b = 2, c = 4 };
X enum_value = X( b | c );
----
Programmer_P: I think, to an extent, macro magic is possible to declare an enum and a conversion to string at the same time.
Okay, this is very simple so it should be easy enough to modify even if you don't use perl (eg, right now the output uses strcpy() and not C++, etc):
Just create a file containing the enum without the containing block {}, eg:Code:#!/usr/bin/perl -w
use strict;
die "Input file required" if (!defined($ARGV[0]));
if (defined $ARGV[1]) {
open(OUT,">".$ARGV[1]) || die "Couldn't open ".$ARGV[1].": $!";
} else { open (OUT, ">&STDOUT") }
open(IN,"<".$ARGV[0]) || die "Couldn't open ".$ARGV[0]."$!";
print OUT "switch (VAR) {\n";
while (<IN>) {
(my $enum = $_) =~ s/[\s|\t]//g;
$enum =~ s/,.*$//;
print OUT "\tcase ($enum):\n"
."\t\tstrcpy(STR_HERE,\"$enum\");\n"
."\t\tbreak;\n";
}
print OUT "\tdefault:\n}\n";
close(IN);
close(OUT);
The comments will be discarded. This is a very common format to cut n' paste, if there are no line breaks or there are comments starting the line :( it will screw up. This produces output like this:Code:ONE, /* comment */
TWO,
THREE, /*comment */
FOUR
So you can search and replace "VAR" and "STR_HERE". If you include a second file name argument, the output is into that file, otherwise it's on STDOUT.Code:switch (VAR) {
case (ONE):
strcpy(STR_HERE,"ONE");
break;
case (TWO):
strcpy(STR_HERE,"TWO");
break;
case (THREE):
strcpy(STR_HERE,"THREE");
break;
case (FOUR):
strcpy(STR_HERE,"FOUR");
break;
default:
}
Thanks.
Not tested, but how about some macro trickery?
Code:#define ENUM_NAME(x) ##x
std::cout << ENUM_NAME(MyEnum);
True, not a perfect solution.
But we could expand this by making our own enum type.