Click here to Skip to main content
15,889,116 members
Articles / Programming Languages / C++
Article

Object Oriented Enumerations

Rate me:
Please Sign up or sign in to vote.
4.62/5 (24 votes)
10 Feb 20054 min read 69.4K   410   32   22
An article on using macros to encapsulate enumerations.

Introduction

Enumerations in C++ are fairly simple. However, in a language that is designed to be strongly-typed, it seems inconsistent to make an exception for enumeration types. For some reason, enumerations are essentially treated as constant integers. This is what I attempted to correct.

I have seen several attempts encapsulating enumerations in classes; however, I have yet to see a simple implementation. Several of them required the use of a compiled utility to create the class. I wanted an implementation that would allow me to use C++ macros to write my enumerations.

Using the code

I separated the macro definitions to make it similar to writing a class. Thus, the definition macros must be used first (e.g., in a header file); however, the implementation macros can be used either right after the definition, or in a source file.

The following is an example taken from the demo project:

// from MyEnums.h
#include "Enumeration.h"

// the EWeekdays definition
BEGIN_ENUM_DEFINITION(Weekdays)
    DEFINE_ENUM(SUNDAY)
    DEFINE_ENUM(MONDAY)
    DEFINE_ENUM(TUESDAY)
    DEFINE_ENUM(WEDNESDAY)
    DEFINE_ENUM(THURSDAY)
    DEFINE_ENUM(FRIDAY)
    DEFINE_ENUM(SATURDAY)
END_ENUM_DEFINITION()
// from MyEnums.cpp
#include "MyEnums.h"

// the EWeekdays implementation
BEGIN_ENUM_IMPLEMENTATION(Weekdays)
    ENUM_ENTRY(EWeekdays::SUNDAY,       "Sunday")
    ENUM_ENTRY(EWeekdays::MONDAY,       "Monday")
    ENUM_ENTRY(EWeekdays::TUESDAY,      "Tuesday")
    ENUM_ENTRY(EWeekdays::WEDNESDAY,    "Wednesday")
    ENUM_ENTRY(EWeekdays::THURSDAY,     "Thursday")
    ENUM_ENTRY(EWeekdays::FRIDAY,       "Friday")
    ENUM_ENTRY(EWeekdays::SATURDAY,     "Saturday")
END_ENUM_IMPLEMENTATION(Weekdays)

The above code creates a class called EWeekdays that encapsulates an enumeration called Weekdays with the day names as the constants.

Documentation

  • BEGIN_ENUM_DEFINITION(theEnumName)

    This macro will create a class with the name theEnumName with a nested enum declaration named theEnumName. It also declares a structure to act as a map. This map allows the enumerated value to be converted to a readable string value. Finally, this also declares several member functions.

  • DEFINE_ENUM_VALUE(enumName, enumValue)

    This macro will add an enumerated value named enumName and set the value to enumValue.

  • DEFINE_ENUM(enumName)

    This macro will add an enumerated value named enumName.

  • DEFINE_LAST_ENUM(enumName)

    This macro is the same as the DEFINE_ENUM macro, but it will leave off the trailing comma. You won't need to use this on most compilers, but technically, it is how ANSI defines the declaration of an enumerated type.

  • END_ENUM_DEFINITION

    This macro ends the declaration of the new enumeration class.

  • BEGIN_ENUM_IMPLEMENTATION(theEnumName)

    This macro starts the implementation of the new enumeration class. theEnumName must match the name given in the BEGIN_ENUM_DEFINITION macro.

  • ENUM_ENTRY(enumValue, enumName)

    This macro adds an entry to the map of names and values. It will map the string value in enumName to the enumValue integer value. It will also assign a value of 0 to the eData member of the map.

  • ENUM_ENTRY_DATA(enumValue, enumName, enumData)

    This macro adds an entry to the map in the same manner as the ENUM_ENTRY macro; however, it allows you to set the data member to some unsigned long value. That is, it can be some meaningful value to your application, or it can be a pointer to another structure. Keep in mind, the map is static, so if you set this value to a pointer, make sure the object that it points to is valid for as long as your enumeration objects are valid (e.g., in scope).

  • END_ENUM_IMPLEMENTATION(theEnumName)

    This macro finishes the implementation. The value in the theEnumName must match the value in the BEGIN_ENUM_IMPLEMENTATION.

Example

The following is an example of what the macros do:

BEGIN_ENUM_DEFINITION(Weekdays)
    DEFINE_ENUM(SUNDAY)
    DEFINE_ENUM(MONDAY)
    DEFINE_ENUM(TUESDAY)
    DEFINE_ENUM(WEDNESDAY)
    DEFINE_ENUM(THURSDAY)
    DEFINE_ENUM(FRIDAY)
    DEFINE_ENUM(SATURDAY)
END_ENUM_DEFINITION()

This declaration creates the following definition:

class EWeekdays 
{ 
public: 
    enum Weekdays; 
protected: 
    Weekdays m_eCurrentValue; 
public: 
    struct SEnumMap 
    { 
        Weekdays eVal; 
        unsigned long eData; 
        const char* eName; 
    }; 
    typedef SEnumMap* Position; 
    typedef SEnumMap* EnumItem; 
protected: 
    static SEnumMap ms_EnumMap[]; 
public: 
    EWeekdays() 
        { m_eCurrentValue = (Weekdays)0; } 
    EWeekdays(const EWeekdays& eVal) 
        { *this = eVal; } 
    EWeekdays(const int& iVal) 
        { m_eCurrentValue = (Weekdays)iVal; } 
    const EWeekdays& operator= (const EWeekdays& eVal) 
        { m_eCurrentValue = eVal.m_eCurrentValue; return *this; } 
    const EWeekdays& operator= (const int& eVal) 
        { m_eCurrentValue = (Weekdays)eVal; return *this; } 
    bool operator==(const EWeekdays& eVal) const 
        { return m_eCurrentValue == eVal.m_eCurrentValue; } 
    bool operator!=(const EWeekdays& eVal) const 
        { return m_eCurrentValue != eVal.m_eCurrentValue; } 
    bool operator< (const EWeekdays& eVal) const 
        { return m_eCurrentValue < eVal.m_eCurrentValue; } 
    bool operator> (const EWeekdays& eVal) const 
        { return m_eCurrentValue > eVal.m_eCurrentValue; } 
    bool operator<=(const EWeekdays& eVal) const 
        { return (*this < eVal || *this == eVal); } 
    bool operator>=(const EWeekdays& eVal) const 
        { return (*this > eVal || *this == eVal); } 
    bool operator==(const int& iVal) const 
        { return m_eCurrentValue == iVal; } 
    bool operator!=(const int& iVal) const 
        { return m_eCurrentValue != iVal; } 
    bool operator< (const int& iVal) const 
        { return m_eCurrentValue < iVal; } 
    bool operator> (const int& iVal) const 
        { return m_eCurrentValue > iVal; } 
    bool operator<=(const int& iVal) const 
        { return (*this < iVal || *this == iVal); } 
    bool operator>=(const int& iVal) const 
        { return (*this > iVal || *this == iVal); } 
    operator int() const 
        { return (int)m_eCurrentValue; } 
    operator const char*() const 
        { return GetEnumName(); } 
    const char* GetEnumName() const 
        { return GetEnumName(*this); } 
    static const char* GetEnumName(const int& iVal) 
        { return GetEnumName((EWeekdays)iVal); } 
    unsigned long GetEnumData() 
        { return GetEnumData(*this); } 
    static unsigned long GetEnumData(const int& iVal) 
        { return GetEnumData((EWeekdays)iVal); } 
    static bool IsValidEnum(const int& iVal) 
        { return IsValidEnum((EWeekdays)iVal); } 
    bool IsValidEnum() 
        { return IsValidEnum(*this); } 
    static const char* GetEnumName(const EWeekdays& eVal); 
    static unsigned int GetCount(); 
    static unsigned long GetEnumData(const EWeekdays& eVal); 
    static EnumItem FindName(const char* name); 
    static bool IsValidEnum(const EWeekdays& eVal); 
    static Position GetFirstEnumPosition(); 
    static const EnumItem GetNextEnumPosition(Position& pos); 
    enum Weekdays 
    { 
        SUNDAY,
        MONDAY,
        TUESDAY,
        WEDNESDAY,
        THURSDAY,
        FRIDAY,
        SATURDAY,
    };
};

You should notice that the static map ms_EnumMap is un-sized, and the static const char* GetEnumName(const EWeekdays& eVal), static unsigned int GetCount(), static unsigned long GetEnumData(const EWeekdays& eVal), static EnumItem FindName(const char* name), static bool IsValidEnum(const EWeekdays& eVal), static Position GetFirstEnumPosition(), and static const EnumItem GetNextEnumPosition(Position& pos) functions are not implemented. These steps are accomplished in the implementation macros below:

BEGIN_ENUM_IMPLEMENTATION(Weekdays)
    ENUM_ENTRY(EWeekdays::SUNDAY,       "Sunday")
    ENUM_ENTRY(EWeekdays::MONDAY,       "Monday")
    ENUM_ENTRY(EWeekdays::TUESDAY,      "Tuesday")
    ENUM_ENTRY(EWeekdays::WEDNESDAY,    "Wednesday")
    ENUM_ENTRY(EWeekdays::THURSDAY,     "Thursday")
    ENUM_ENTRY(EWeekdays::FRIDAY,       "Friday")
    ENUM_ENTRY(EWeekdays::SATURDAY,     "Saturday")
END_ENUM_IMPLEMENTATION(Weekdays)

The above set of macros implements the last steps of the enumeration class:

EWeekdays::SEnumMap EWeekdays::ms_EnumMap[] = 
    {
        { EWeekdays::SUNDAY,    0,    "Sunday" },
        { EWeekdays::MONDAY,    0,    "Monday" },
        { EWeekdays::TUESDAY,    0,    "Tuesday" },
        { EWeekdays::WEDNESDAY,    0,    "Wednesday" },
        { EWeekdays::THURSDAY,    0,    "Thursday" },
        { EWeekdays::FRIDAY,    0,    "Friday" },
        { EWeekdays::SATURDAY,    0,    "Saturday" },
    };
const char* EWeekdays::GetEnumName(const EWeekdays& eVal)
{
    Position pos = GetFirstEnumPosition();
    while (0 != pos)
    {
        EnumItem pVal = GetNextEnumPosition(pos);
        if (pVal->eVal == eVal)
            return pVal->eName;
    }
    return 0;
}
unsigned int EWeekdays::GetCount()
{ return (unsigned int)(sizeof(ms_EnumMap) / sizeof(ms_EnumMap[0])); }
unsigned long EWeekdays::GetEnumData(const EWeekdays& eVal)
{
    Position pos = GetFirstEnumPosition();
    while (0 != pos)
    {
        EnumItem pVal = GetNextEnumPosition(pos);
        if (pVal->eVal == eVal)
            return pVal->eData;
    }
    return 0;
}
EWeekdays::EnumItem EWeekdays::FindName(const char* name)
{
    Position pos = GetFirstEnumPosition();
    while (0 != pos)
    {
        EnumItem pVal = GetNextEnumPosition(pos);
        if (0 == strcmp(name, pVal->eName))
            return pVal;
    }
    return 0;
}
bool EWeekdays::IsValidEnum(const EWeekdays& eVal)
{
    Position pos = GetFirstEnumPosition();
    while (0 != pos)
    {
        EnumItem pVal = GetNextEnumPosition(pos);
        if (pVal->eVal == eVal)
            return true;
    }
    return false;
}
EWeekdays::Position EWeekdays::GetFirstEnumPosition()
{
    return &ms_EnumMap[0];
}
const EWeekdays::EnumItem EWeekdays::GetNextEnumPosition(EWeekdays::Position& pos)
{
    EnumItem ret = pos;
    if (pos < &ms_EnumMap[GetCount() - 1])
        pos++;
    else
        pos = 0;
    return ret;
}

Points of Interest

You should note that you can make multiple enum entries that have the same integer values; however, when using the (const char*) operator to get the name of them, it will return the string corresponding to the first one found. If you do create multiple entries, you should use the same string for them as well.

This revision no longer suffers from the limitation of having to start at 0. Now, not only can you start anywhere, but the enumeration values do not have to be concurrent.

// from MyEnums.h
// the EFoodGroups defintion
BEGIN_ENUM_DEFINITION(FoodGroups)
    DEFINE_ENUM_VALUE(GRAIN, -2)
    DEFINE_ENUM_VALUE(MEAT, 4)
    DEFINE_ENUM_VALUE(FRUIT, 9)
    DEFINE_ENUM(VEGETABLE)
END_ENUM_DEFINITION()

The code above declares an enumeration with values at -2, 4, 9, and 10. To accommodate this, I added GetFirstEnumerationPosition and GetNextEnumerationPosition functions. If you are defining enumerations this way, you will need to use these functions to iterate through the enumeration. If your numbers are concurrent, you can still use a for-style loop if you like, though.

Since several of you requested a way to go from strings to enumerations, I came up with a way to accommodate that ability without making it too much of a headache. The FindName member function will iterate through the enumeration and attempt to find a match for the name (keep in mind, it will stop on the first match it finds). If successful, it returns a EnumItem (which is a typedef for a SEnumMap*). If it fails, it returns 0. I realize this falls a half-step short of an assignment operator for strings, but I needed some way to do error checking. To do an assignment using this, you would do something like the following:

EWeekday Day = EWeekday::SUNDAY;
const char* MyDay = "Saturday";
EWeekdays::EnumItem item = EWeekdays::FindName(MyDay);
if (0 != item)
{
    Day = item->eVal;
}
else
{
    // not found, do something here
}

You will also notice the addition of three IsEnumValid member functions. These functions allow you to check to see if a particular value is valid for this enumeration.

History

  • 2005/01/30 - Original.
  • 2005/02/04 - Uploaded correct sample code and added ANSI-compliant definition macro.
  • 2005/02/09 - Added some significant features (data member for map, name search, iteration functions, validity checks).

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
I started programming at 15 with a TI-82 calclator in Z80 assembly (oh, those were the days . . .) I am pretty much a self taught programmer. I've taught myself Visual Basic, C/C++, Java, and am currently working on C#. I also like to experiment with system administration and security issues, and occassionally I work on web design. For the last 4 years, I have worked for Leitch, Inc. as a Software Engineer and graduated from Old Dominion University with bachelor's degrees in Computer Science, Mathematics, and Business Management in December of 2004.

Comments and Discussions

 
NewsReplacement to std::string Pin
juanpablohv12-Aug-14 4:16
juanpablohv12-Aug-14 4:16 
First, thanks so much for the code! I played with it and I like it very much!!!

As I really don't like to use char* in my C++ applications, I decided to switch to std::string. So on this version you will see these changes:
1) Define name as std::string eName;
2) To avoid dummy copies of std::string objects, I decided to return const std::string& to current enumeration's Name.
3) To deal with the case where you cannot find the name of a key, a static member ms_UnknowName is defined as classname_UNKNOWN to have a valid reference in the previous point.

To have a friendly string conversion you have:
4) .ToString() method returns const std::string&
5) .ToChar() method returns const char*

As I would like to use it in DLLs, it's important to put code for beginners:
6) See notes about ENUMERATION_COMMON_EXPORT macro definition


Some examples for EnumTester.cpp:
C++
cout<<"Enum Value = "<<MyDays<<", Name = "<<(std::string)MyDays<< ", same as = "<<MyFruits.ToString()<<endl;
// Same as
cout<<"Enum Value = "<<MyDays<<", Name = "<<(const char*)MyDays<< ", same as = "<<MyDays.ToChar()<<endl;
// Or
printf("Enum Value = %d, Name = %s\n", MyFruits, MyFruits.ToChar());


Output for a Enumeration that does not exists:
Validity checks
Is -1 valid for EWeekdays?      No
   -1 in EWeekdays is:  EWeekdays_UNKNOWN
   EWeekdays_UNKNOWN in EWeekdays exists?:      No



Version of the code: Enumeration.h
C++
// This is a set of macros designed to make a type-safe enumeration class
// Copyright (c) 2005, James Zachary Howland.  All rights reserved.
//
// This code is free to use in both personal and commercial applications so
// long as the comments in the first 22 lines of this file are unchanged.
// If you make any additions, find any bugs, or wish to make any suggestions
// feel free to email the original author at zachowland@hotmail.com.  If your
// comments lead to further development of this project, I will add your name
// to the credits section below.
///////////////////////////////////////////////////////////////////////////////
// CREDITS:     James Zachary Howland, Original Author
//              David Heath and Zigge, requested const char*->enum feature
//              Juan Pablo Hernandez Vogt, use std::string, code for DLL in VS
//
///////////////////////////////////////////////////////////////////////////////
// NOTE:	For this class to work correctly, each enum constant must be unique
//              If duplicate values are used, it is impossible to obtain the correct
//              string name when using the const char*() operator.
//              A workaround for this is to use the same string names if you use
//              the same value for multiple constant names
//
///////////////////////////////////////////////////////////////////////////////

#pragma once 

// Use cases for Visual Studio:
// 1) Basic case: all code in your project, nothing to define
//
// 2) DLL case: if you want to use Enumeration outside the DLL
//    2.a) Add Preprocessor Macro ENUMERATION_COMMON_EXPORT in your DLL project
//    2.b) Add Preprocessor Macro ENUMERATION_COMMON_IMPORT in projects that uses the DLL
//

#ifdef _MSC_VER
	#ifdef ENUMERATION_DLL_EXPORT
		#define ENUMERATION_COMMON_EXPORT __declspec( dllexport )
	#elseif ENUMERATION_DLL_IMPORT
		#define ENUMERATION_COMMON_EXPORT __declspec( dllimport )
	#else
		#define ENUMERATION_COMMON_EXPORT
	#endif
#else
	#define ENUMERATION_COMMON_EXPORT
#endif


#include <string>

#define BEGIN_ENUM_DEFINITION(theEnumClass) \
	class ENUMERATION_COMMON_EXPORT E##theEnumClass \
	{ \
	public: \
		enum theEnumClass; \
	protected: \
		theEnumClass m_eCurrentValue; \
	public: \
		struct SEnumMap \
		{ \
			theEnumClass eVal; \
			unsigned long eData; \
			std::string eName; \
		}; \
		typedef SEnumMap* Position; \
		typedef SEnumMap* EnumItem; \
	protected: \
		static SEnumMap ms_EnumMap[]; \
		static const std::string ms_UnknowName; \
	public: \
		E##theEnumClass() \
			{ m_eCurrentValue = (theEnumClass)0; } \
		E##theEnumClass(const E##theEnumClass& eVal) \
			{ *this = eVal; } \
		E##theEnumClass(const int& iVal) \
			{ m_eCurrentValue = (theEnumClass)iVal; } \
		const E##theEnumClass& operator= (const E##theEnumClass& eVal) \
			{ m_eCurrentValue = eVal.m_eCurrentValue; return *this; } \
		const E##theEnumClass& operator= (const int& eVal) \
			{ m_eCurrentValue = (theEnumClass)eVal; return *this; } \
		bool operator==(const E##theEnumClass& eVal) const \
			{ return m_eCurrentValue == eVal.m_eCurrentValue; } \
		bool operator!=(const E##theEnumClass& eVal) const \
			{ return m_eCurrentValue != eVal.m_eCurrentValue; } \
		bool operator< (const E##theEnumClass& eVal) const \
			{ return m_eCurrentValue < eVal.m_eCurrentValue; } \
		bool operator> (const E##theEnumClass& eVal) const \
			{ return m_eCurrentValue > eVal.m_eCurrentValue; } \
		bool operator<=(const E##theEnumClass& eVal) const \
			{ return (*this < eVal || *this == eVal); } \
		bool operator>=(const E##theEnumClass& eVal) const \
			{ return (*this > eVal || *this == eVal); } \
		bool operator==(const int& iVal) const \
			{ return m_eCurrentValue == iVal; } \
		bool operator!=(const int& iVal) const \
			{ return m_eCurrentValue != iVal; } \
		bool operator< (const int& iVal) const \
			{ return m_eCurrentValue < iVal; } \
		bool operator> (const int& iVal) const \
			{ return m_eCurrentValue > iVal; } \
		bool operator<=(const int& iVal) const \
			{ return (*this < iVal || *this == iVal); } \
		bool operator>=(const int& iVal) const \
			{ return (*this > iVal || *this == iVal); } \
		operator int() const \
			{ return (int)m_eCurrentValue; } \
		operator const std::string&() const \
			{ return GetEnumName(); } \
		operator const char*() const \
			{ return ToChar(); } \
		inline \
		const std::string& GetEnumName() const \
			{ return GetEnumName(*this); } \
		inline \
		const std::string& ToString() const \
			{ return GetEnumName(); } \
		inline \
		const char* ToChar() const \
			{ return GetEnumName().c_str(); } \
		static const std::string& GetEnumName(const int& iVal) \
			{ return GetEnumName((E##theEnumClass)iVal); } \
		unsigned long GetEnumData() \
			{ return GetEnumData(*this); } \
		static unsigned long GetEnumData(const int& iVal) \
			{ return GetEnumData((E##theEnumClass)iVal); } \
		static bool IsValidEnum(const int& iVal) \
			{ return IsValidEnum((E##theEnumClass)iVal); } \
		bool IsValidEnum() \
			{ return IsValidEnum(*this); } \
		static const std::string& GetEnumName(const E##theEnumClass& eVal); \
		static unsigned int GetCount(); \
		static unsigned long GetEnumData(const E##theEnumClass& eVal); \
		static EnumItem FindName(std::string name); \
		static bool IsValidEnum(const E##theEnumClass& eVal); \
		static Position GetFirstEnumPosition(); \
		static const EnumItem GetNextEnumPosition(Position& pos); \
		enum theEnumClass \
		{ \

#define DEFINE_ENUM_VALUE(enumName, enumValue) \
			enumName = enumValue,\

#define DEFINE_ENUM(enumName) \
			enumName,\

#define DEFINE_LAST_ENUM(enumName) \
			enumName \

#define END_ENUM_DEFINITION() \
		}; \
	}; \

#define BEGIN_ENUM_IMPLEMENTATION(theEnumClass) \
	ENUMERATION_COMMON_EXPORT const std::string E##theEnumClass::ms_UnknowName("E"#theEnumClass"_UNKNOWN"); \
	E##theEnumClass::SEnumMap E##theEnumClass::ms_EnumMap[] = \
		{ \

#define ENUM_ENTRY(enumValue, enumName) \
			{enumValue, 0L, enumName}, \

#define ENUM_ENTRY_DATA(enumValue, enumName, enumData) \
			{enumValue, enumData, enumName}, \

#define END_ENUM_IMPLEMENTATION(theEnumClass) \
		}; \
	const std::string& E##theEnumClass::GetEnumName(const E##theEnumClass& eVal) \
	{ \
		Position pos = GetFirstEnumPosition(); \
		while (0 != pos) \
		{ \
			EnumItem pVal = GetNextEnumPosition(pos); \
			if (pVal->eVal == eVal) \
				return pVal->eName; \
		} \
		return ms_UnknowName; \
	} \
	unsigned int E##theEnumClass::GetCount() \
	{ return (unsigned int)(sizeof(ms_EnumMap) / sizeof(ms_EnumMap[0])); } \
	unsigned long E##theEnumClass::GetEnumData(const E##theEnumClass& eVal) \
	{ \
		Position pos = GetFirstEnumPosition(); \
		while (0 != pos) \
		{ \
			EnumItem pVal = GetNextEnumPosition(pos); \
			if (pVal->eVal == eVal) \
				return pVal->eData; \
		} \
		return 0; \
	} \
	E##theEnumClass::EnumItem E##theEnumClass::FindName(std::string name) \
	{ \
		Position pos = GetFirstEnumPosition(); \
		while (0 != pos) \
		{ \
			EnumItem pVal = GetNextEnumPosition(pos); \
			if (name.compare(pVal->eName) == 0) \
				return pVal; \
		} \
		return 0; \
	} \
	bool E##theEnumClass::IsValidEnum(const E##theEnumClass& eVal) \
	{ \
		Position pos = GetFirstEnumPosition(); \
		while (0 != pos) \
		{ \
			EnumItem pVal = GetNextEnumPosition(pos); \
			if (pVal->eVal == eVal) \
				return true; \
		} \
		return false; \
	} \
	E##theEnumClass::Position E##theEnumClass::GetFirstEnumPosition() \
	{ \
		return &ms_EnumMap[0]; \
	} \
	const E##theEnumClass::EnumItem E##theEnumClass::GetNextEnumPosition(E##theEnumClass::Position& pos) \
	{ \
		EnumItem ret = pos; \
		if (pos < &ms_EnumMap[GetCount() - 1]) \
			pos++; \
		else \
			pos = 0; \
		return ret; \
	} \


Updated version of main app: EnumTester.cpp
Note: I put different ways to get the constant name
C++
// EnumTester.cpp : Defines the entry point for the console application.
//

#include <stdio.h>
#include <conio.h>
#include <iostream>
#include "MyEnums.h"

using namespace std;

void main()
{
	printf("Weekdays enumeration\n");
	EWeekdays::Position i = EWeekdays::GetFirstEnumPosition();
	while (0 != i)
	{
		EWeekdays::EnumItem item = EWeekdays::GetNextEnumPosition(i);
		EWeekdays MyDays = item->eVal;
		cout<<"Enum Value = "<< MyDays <<", Name = " << (std::string)MyDays << ", same as = "<<MyDays.ToChar()<<endl;
		if (MyDays == 5)	// integer comparison
		{
			cout<<"My Favorite Day:  "<<MyDays.GetEnumName()<<endl;
		}
	}

	printf("\nFruits enumeration\n");
	EFruits::Position j = EFruits::GetFirstEnumPosition();
	while (0 != j)
	{
		EFruits::EnumItem item = EFruits::GetNextEnumPosition(j);
		EFruits MyFruits = item->eVal;
		printf("Enum Value = %d, Name = %s\n", MyFruits, MyFruits.ToString().c_str());
		if (MyFruits == EFruits::KIWI && 1 == MyFruits.GetEnumData())	// strong-typed comparison, data comparison
		{
			printf("My Favorite Fruit:  %s\n", MyFruits.GetEnumName().c_str());
		}
	}

	printf("\nFoodGroups enumeration\n");
	EFoodGroups::Position k = EFoodGroups::GetFirstEnumPosition();
	while (0 != k)
	{
		EFoodGroups::EnumItem item = EFoodGroups::GetNextEnumPosition(k);
		EFoodGroups MyFoodGroups = item->eVal;
		printf("Enum Value = %d, Name = %s\n", MyFoodGroups, MyFoodGroups.ToChar());
	}

	cout << "\nValidity checks" << endl;
	cout << "Is -1 valid for EWeekdays?\t" << (EWeekdays::IsValidEnum(-1) ? "Yes" : "No") << endl;
	cout << "   -1 in EWeekdays is:\t" << EWeekdays::GetEnumName(-1) << endl;
	cout << "   "<<EWeekdays::GetEnumName(-1)<<" in EWeekdays exists?:\t" << (EWeekdays::FindName(EWeekdays::GetEnumName(-1)) ? "Yes" : "No") << endl;
	cout << endl;
	cout << "Is 3 valid for EFruits?\t" << (EFruits::IsValidEnum(3) ? "Yes" : "No") << endl;
	cout << "   3 in EFruits is:\t" << EFruits::GetEnumName(3) << endl;

	_getch();
}

GeneralYour code sucks Pin
quickhidethehead26-Jun-06 13:52
quickhidethehead26-Jun-06 13:52 
GeneralRe: Your code sucks Pin
juanpablohv12-Aug-14 4:33
juanpablohv12-Aug-14 4:33 
GeneralMy enhancements Pin
Uwe Keim10-Apr-06 19:54
sitebuilderUwe Keim10-Apr-06 19:54 
GeneralRe: My enhancements Pin
Uwe Keim10-Apr-06 19:55
sitebuilderUwe Keim10-Apr-06 19:55 
GeneralCan't compile with VC7.0 Pin
rromerot12-Feb-05 18:22
rromerot12-Feb-05 18:22 
GeneralRe: Can't compile with VC7.0 Pin
Zac Howland12-Feb-05 20:08
Zac Howland12-Feb-05 20:08 
GeneralRe: Can't compile with VC7.0 Pin
rromerot14-Feb-05 0:06
rromerot14-Feb-05 0:06 
GeneralRe: Can't compile with VC7.0 Pin
rromerot14-Feb-05 1:14
rromerot14-Feb-05 1:14 
GeneralRe: Can't compile with VC7.0 Pin
Zac Howland14-Feb-05 6:18
Zac Howland14-Feb-05 6:18 
GeneralUNICODE-Aware Pin
Uwe Keim11-Feb-05 1:05
sitebuilderUwe Keim11-Feb-05 1:05 
GeneralRe: UNICODE-Aware Pin
Zac Howland11-Feb-05 3:56
Zac Howland11-Feb-05 3:56 
GeneralI don't comment on here much... Pin
Diarrhio10-Feb-05 20:54
Diarrhio10-Feb-05 20:54 
GeneralRe: I don't comment on here much... Pin
Zac Howland11-Feb-05 3:48
Zac Howland11-Feb-05 3:48 
GeneralGood, and a request for enhancements ! Pin
Zigge7-Feb-05 5:15
Zigge7-Feb-05 5:15 
GeneralRe: Good, and a request for enhancements ! Pin
Zac Howland8-Feb-05 5:52
Zac Howland8-Feb-05 5:52 
GeneralRe: Good, and a request for enhancements ! Pin
ThatsAlok8-Feb-05 18:36
ThatsAlok8-Feb-05 18:36 
GeneralRe: Good, and a request for enhancements ! Pin
Zac Howland9-Feb-05 6:51
Zac Howland9-Feb-05 6:51 
GeneralRe: Good, and a request for enhancements ! Pin
Zigge8-Feb-05 20:53
Zigge8-Feb-05 20:53 
GeneralRe: Good, and a request for enhancements ! Pin
Zac Howland9-Feb-05 6:50
Zac Howland9-Feb-05 6:50 
GeneralANSI Pin
Guy Baseke3-Feb-05 4:12
Guy Baseke3-Feb-05 4:12 
GeneralRe: ANSI Pin
Zac Howland4-Feb-05 6:17
Zac Howland4-Feb-05 6:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.