Using C++ enums like C# enums

There is an update to this post: Re: Using C++ enums like C# enums

I’ve been playing around with idea for a while in my head, a way to have enums work similar to how they work in C#, where they are part of an object.

Usually I would do this.

enum BufferFlags
{
	kBufferFlags_Read = 1 << 0,
	kBufferFlags_Write = 1 << 1
};

 

Since I prefix all my enums with kBufferFlags_, so to access the read enum I’d write kBufferFlags_Read. I can reduce out this bit of code in C# to be an enum object called BufferFlags, and have enums Read and Write. Accessing them with BufferFlags.Read.

So how do I do it in C++? By putting the enum within a struct, I can access them with BufferFlags::Read. Not quite the same, but better. However the structure needs to operate like an enum, so I overloaded the cast operator to return the enum, and the assignment and copy constructors to take the enum too.

I choose to keep the internal value hidden, but it can all be public.

#define ATHENA_START_CSHARP_ENUM( x ) struct x \
{ \
public: \
	enum xEnum; \
\
	inline x() \
	{ \
	} \
\
	inline x( const xEnum inValue ) \
		: \
		value( inValue ) \
	{ \
	} \
\
	inline void operator = ( const xEnum inValue ) \
	{ \
		value = inValue; \
	} \
\
	inline operator xEnum () const \
	{ \
		return value; \
	} \
\
private: \
	xEnum value; \
\
public: \
	enum xEnum
 
#define ATHENA_END_CSHARP_ENUM() ; \
};

 

Originally, the end macro use to take in the name of the enum as well. The reason for this was that the variable value used its type so when viewed in the debugger I could see its value as an enum name instead of a number.

So I changed the enum to be forward declared. To use this macro you now declare an enum like this.

ATHENA_START_CSHARP_ENUM( BufferFlags )
{
	Read = 1 << 0,
	Write = 1 << 1
}
ATHENA_END_CSHARP_ENUM()

 

And an example of it in use.

int main()
{
	BufferFlags flags = BufferFlags::Read;
 
	//
	switch( flags )
	{
	case BufferFlags::Read:
		break;
 
	case BufferFlags::Write:
		break;
 
	default:
		break;
	}
 
	//
	return 0;
}

 

Its a bit more hassle to use it, but it does look nicer to look at when used.