なんとな~くしあわせ?の日記

「そしてそれゆえ、知識そのものが力である」 (Nam et ipsa scientia potestas est.) 〜 フランシス・ベーコン

列挙型の管理(C++)

定義した列挙型の数が多くて困る

wxWidgetsでソースを書いていると、制御用の列挙型の定義がどんどん多くなっていく。列挙型を定義することで、プログラム自体は書きやすくなるのですが…あと列挙型を文字列として取り出したくなってきた。

EnumString.h

最低一回は定義を書くとしても、それ以外は書きたくない。
解決法はいろいろあったけど以下2つを組み合わせた
Enum to String and Vice Versa in C++ - CodeProject
c++ - Easy way to use variables of enum types as string in C? - Stack Overflow

最初のEnum-to-Stringは、配布されている「EnumString.h」をインクルードすることで、列挙型を容易にstd::stringで取り出せるようになる。

簡単な使い方

列挙型を定義してEnum_String内に放り込む。
Enum_String()自体は簡単なマクロである。

/**
 * 定義
 */
enum WeekEnd {
    Sunday = -1;
    Saturday
};

Begin_Enum_String( WeekEnd )
{
    Enum_String( Sunday );
    Enum_String( Saturday );
}
End_Enum_String;

/**
 * 取り出し
 */
// 列挙型WeekEndをstringに変換
const std::string &str = EnumString<WeekEnd>::From( Saturday );
// str の中身は "Saturday" になるはず
// 単なるint型からキャストも可能
int i = 0;
const std::string &str = EnumString<WeekEnd>::From( static_cast<WeekEnd>(i) );

// 使うかわからないけど、stringから列挙型への変換
WeekEnd w;
EnumString<WeekEnd>::To( w, "Sunday" );
// w は列挙型のSundayになる
X() macros

上記だけでは結局列挙型の定義と文字列化で、定義を2回書くことになる。それは勘弁してくれなので、マクロを使ってみる。

#ifndef PREPROCESSOR_HPP_
#define PREPROCESSOR_HPP_

#include "enumstring.hpp"

// マクロ文字列化
#define XSTR(x) #x
#define STR(x)  XSTR(x)

// テーブル要素
#define X_TABLE_ITEM(x) X(x, STR(x))
// 使いたい列挙型を定義する
#define X_TABLE \
     X_TABLE_ITEM(ID_Hoge) \
     X_TABLE_ITEM(ID_Fuga) \
     X_TABLE_ITEM(ID_Piyo) \
     X_TABLE_ITEM(ID_End)

// 列挙型の実体をマクロで生成する
typedef enum {
     ID_Begin = -1,
     #define X(Enum, String) Enum,
     X_TABLE
     #undef X
} TEST_ENUMS;

// 文字列化
Begin_Enum_String( TEST_ENUMS )
{

#define X(Enum, String)					\
     Enum_String( Enum )                                \

     X_TABLE
#undef X

}
End_Enum_String;


#endif /* PREPROCESSOR */

上記で一応列挙型の宣言と文字列化が一度に実施できると思う。