// This code is in the public domain.
// Author: Walt Karas
// Provides the macros ENUM_DEFINE and ENUM_LOOKUP for defining
// enums and static lookup tables from the enum values. To avoid
// name conflicts, don't declare names that begin with ENUM_ or
// end with _enum_. Names declared in this file that end with _
// are "private".
#ifndef ENUM_HPP_
#define ENUM_HPP_
// Defines a enum whose name is NAME. LIST must be the name of
// a parameterless macro of the form:
// #define ABC_LIST(E, S) E(N1) S E(N2) S ... S E(Nm)
// where N1, N2, ... Nm are the names of the enum elements.
//
// Example Usage:
// #define COLOR_LIST(EL, SEP) \
// EL(Color_red) SEP EL(Color_green) SEP EL(Color_blue)
// ENUM_DEFINE(Color, COLOR_LIST)
//
// equivalent to:
// enum Color { Color_red, Color_green, Color_blue };
//
#define ENUM_DEFINE(NAME, LIST) \
enum NAME { LIST(ENUM_DEFINE_AUX_, ENUM_COMMA_) , NAME##_num_elems };
// Defines a const array whose name is LOOKUP_NAME. The type of the array
// elements is RESULT_TYPE. ENUM_NAME and ENUM_LIST must be the NAME
// and LIST parameters passed to a preceeding invocation of ENUM_DEFINE.
// LOOKUP_LIST must be a parameterless macro of the form:
// #define ABC_LIST(E, S) E(N1, V1) S E(N2, V2) S ... S E(Nm, Vm)
// where each Ni is the name of an element of the enum ENUM_NAME, and
// Vi is the value to be given to array element LOOKUP_NAME[Ni]. The
// enum element names don't have to be in the same order in LOOKUP_LIST
// as they are in ENUM_LIST. A (cryptic) compiler error will result
// if any enum element names are missing from LOOKUP_LIST.
//
// Example Usage (based on ENUM_DEFINE example):
// #define COLOR_STR_LIST(E, S) \
// E(Color_green, "Green") S E(Color_blue, "Blue") S E(Color_red, "Red)
// ENUM_LOOKUP(Color, COLOR_LIST, Color_str, char *, COLOR_STR_LIST
//
// equivalent to:
// const char *Color_str[] = { "Red", "Green", "Blue" };
//
#define ENUM_LOOKUP( \
ENUM_NAME, ENUM_LIST, LOOKUP_NAME, RESULT_TYPE, LOOKUP_LIST) \
namespace LOOKUP_NAME##_enum_ { \
typedef RESULT_TYPE Result_type; \
template struct V; \
LOOKUP_LIST(ENUM_LOOKUP_AUX1_, ENUM_EMPTY_) \
const RESULT_TYPE lookup[] = \
{ ENUM_LIST(ENUM_LOOKUP_AUX2_, ENUM_COMMA_) }; } \
const RESULT_TYPE * const LOOKUP_NAME = LOOKUP_NAME##_enum_::lookup;
/////////////////////// Begin Private Stuff ////////////////////////
// Some compilers don't like empty macro paramters, but all are happy
// with a macro that evaluates to nothing.
#define ENUM_EMPTY_
// Useful for passing a comma as a parameter to a macro.
#define ENUM_COMMA_ ,
#define ENUM_DEFINE_AUX_(ELEM) ELEM
#define ENUM_LOOKUP_AUX1_(ELEM, RESULT) \
template<> struct V \
{ static const Result_type Val = (RESULT); };
#define ENUM_LOOKUP_AUX2_(ELEM) V::Val
#endif
               (
geocities.com/wkaras)