Skip to main content
gamedev.net
🔒 Locked

[C++] enums

Started by Sijmen 10 replies 1.3k views
Original Post
Sijmen
Sijmen
Hi there, I'm a bit confused with enums in C++. I've been used to them with C#, but it's a bit unclear to me how they work with C+++. Take a look at this code for example:

enum Fruit {
        Banana,
        Pineappele,
        Apple
};

enum Brand {
        Dell,
        Apple,
        IBM
};

int main(int argc, char** argv) {
        Fruit favouriteFruit = Banana;
        Brand favouriteBrand = Apple;

        return 0;
}



This does not compile, as enum values aren't named by EnumName.ValueName, but only by ValueName, so both 'Apple' declarations are in the same namespace, and thus invalid. Am I using the enum type in a wrong way? Or should I do something else different?
rip-off
rip-off
This shouldn't compile:

sorry...

enum Fruit {        Banana,        Pineappele,        Apple};enum Brand {        Dell,        Apple,        IBM};int main(int argc, char** argv) {        Fruit favouriteFruit = Fruit::Banana;        Brand favouriteBrand = Brand::Apple;        return 0;}


[Edited by - rip-off on February 1, 2006 10:35:31 AM]
Spoonbender
Spoonbender
You're pretty much right, that's how it works. In C++, enums are just a very weakly disguised int's. Don't expect it to enforce them as separate types (or allow multiple enum values to share the same name).

One often used solution is to prefix each value with some identifier.
For example, all the entries in Fruit could be prefixed with FR_, and Brand entries with BR_
Or you could put them in separate namespaces.
(Or do as rip-off said, which might be a bit prettier [wink])
nmi
nmi
Quote:
Original post by rip-off
This should compile:

*** Source Snippet Removed ***

The operator "::" is similar to using the dot operator when access static data members of a class. Here it means "use Brand's Apple as opposed to any other Apple".


That's not really the problem. And it also won't compile, at least for MinGW 3.4.4. Did you even try to compile your suggestion ?

The declaration for Apple is duplicate, since a declaration like
enum Fruit { Apple };

is almost the same as a declaration like
static const int Apple = 0;

The difference between an 'enum' and 'static const int' is that for enumerators only valid values may be selected, i.e. in
Brand favouriteBrand = Apple;


BTW an assignment like
Brand favouriteBrand = Brand::Apple;

won't work.
rip-off
rip-off
You are most correct nmi

However, at least for me, this seems like something c++ could support with little difficulty. It would be consistent with the rest of the language. That doesn't change the fact that it doesn't work [embarrass]. Sorry for the misinformation.
Sijmen
Sijmen
Okay, that made things clear.

But on to the other side of the problem: what's the C++ method of achieving the desired effect? Or is prefixing the way to go?
rip-off
rip-off
Quote:
Original post by Sijmen
Okay, that made things clear.

But on to the other side of the problem: what's the C++ method of achieving the desired effect? Or is prefixing the way to go?


You could use a namespace:
namespace Fruits{enum Fruit{Apple, Banana, Pear,};}namespace Brands{enum Brand{Apple, Dell, IBM,};}int main(int argc, char **argv){    Fruits::Fruit favouriteFruit = Fruits::Banana;    Brands::Brand favouriteBrand = Brands::Apple;    return 0;}
Nitage
Nitage
namespace fruit{   enum fruit   {        Banana,        Pineappele,        Apple   };}namespace brand{    enum brand    {        Dell,        Apple,        IBM    };}using namespace fruit;using namespace brand;int main(int argc, char** argv){    fruit favouriteFruit = fruit::Banana;    brand favouriteBrand = brand::Apple;    return 0;}
Enigma
Enigma
My preference is to introduce a real UDT. Some people consider this too heavyweight in terms of lines of code but it has the benefit of disallowing uninitialised values:
class Fruit{	public:		static Fruit const Banana;		static Fruit const Pineapple;		static Fruit const Apple;		bool operator==(Fruit const & fruit)		{			return id_ == fruit.id_;		}	private:		Fruit(unsigned int id)			:			id_(id)		{		}		unsigned int id_;};Fruit const Fruit::Banana = Fruit(1);Fruit const Fruit::Pineapple = Fruit(2);Fruit const Fruit::Apple = Fruit(3);class Brand{	public:		static Brand const Dell;		static Brand const Apple;		static Brand const IBM;		bool operator==(Brand const & brand)		{			return id_ == brand.id_;		}	private:		Brand(unsigned int id)			:			id_(id)		{		}		unsigned int id_;};Brand const Brand::Dell = Brand(1);Brand const Brand::Apple = Brand(2);Brand const Brand::IBM = Brand(3);int main(){	Fruit favouriteFruit = Fruit::Banana;	Brand favouriteBrand = Brand::Apple;}

(it also has the advantage of compiling, unlike Nitage's example [wink])

Σnigma
nmi
nmi
How about this version:
struct Fruit{	enum EnumType	{		Banana,		Pineappele,		Apple	};		EnumType value;		Fruit(EnumType v)	{		value = v;	}		Fruit& operator= (EnumType v)	{		value = v;		return *this;	}		Fruit& operator= (const Fruit& that)	{		value = that.value;		return *this;	}		operator EnumType ()	{		return value;	}};int bar(){    Fruit favouriteFruit = Fruit::Banana;    return 0;}


(BTW it should compile fine... ;-)

You can wrap it into a macro definition and extend it as necessary.
Sijmen
Sijmen
Thanks for all the answers! That's more than enough to get me going.
GDN001TB
GDN001TB
One last thing, enum values are consecutive values.
enum{  a,  b,  c,};and enum{  red,  green,  blue,};


a = red = 0;
b = green = 1;
c = blue = 2;

if your "apple" value doesnt have the same position, it wont be equal.

To fix it you may try to give starting value to the shorter list, but it would still need for both enums to be ordered sequentially.

enum{  b = 1,  c,};



Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.