[C++] 列挙体 (enum) から名前(文字列)を取得するマクロ

  • ????????????????????

C/C++ には列挙体があります。列挙体のタグは内部的には整数型として扱われますが、時々、タグの名前を文字列として取得できると便利だな、と思うことがあります。

マクロを使うと割と簡単に実現できます。下のソースコードの DECLARE_ENUM がそのマクロです。可変引数マクロを使っています。その下の main 関数の中では color という列挙体と colorName という文字列配列をDECLARE_ENUM マクロを使って同時に宣言しています。

この手のことはもちろん、文字列配列をまじめに定義すればよいのでどのくらい意味があるかはわかりませんが…
まあ、二度同じことを書かなくてよいのでタイピングは減るということがメリットでしょうか。

#include <iostream>
#include <string>
#include <vector>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>

using namespace std;

#define DECLARE_ENUM(enumname, enumstr, ...)   \
enum enumname {__VA_ARGS__};                   \
boost::algorithm::split(enumstr, #__VA_ARGS__, boost::is_any_of(",")); \
do { BOOST_FOREACH(std::string &s, enumstr){ boost::trim(s); } } while(0)

int main()
{
  /* color is enum / colorName is vector<string> */
  vector<string> colorName;

  DECLARE_ENUM(color, colorName, RED, BLUE, GREEN);

  cout << RED   << ": " << colorName[RED] << endl;
  cout << BLUE  << ": " << colorName[BLUE] << endl;
  cout << GREEN << ": " << colorName[GREEN] << endl;
}

出力結果

0: RED
1: BLUE
2: GREEN

上の方法の欠点は定義をグローバルな場所に書くことができないことです。列挙体はグローバル変数として定義されることも多いのでこれは問題かもしれません。しかし、すこし書き換えればこの問題は回避できます。

#include <iostream>
#include <string>
#include <vector>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>

using namespace std;

struct __EnumName {
  __EnumName(string str)
  {
    boost::algorithm::split( _strvec , str, boost::is_any_of(","));
    BOOST_FOREACH(std::string &s, _strvec ){
      boost::trim(s);
    }
  }
  string operator[](int i){
    return _strvec[i];
  }
private:
  vector<string> _strvec;
};

#define DECLARE_ENUM(enumname, enumstr, ...)   \
enum enumname {__VA_ARGS__};                   \
__EnumName enumstr( #__VA_ARGS__ )

/* color is enum / colorName is vector<string> */
DECLARE_ENUM(color, colorName, RED, BLUE, GREEN);   // <= グローバル宣言

int main()
{
  cout << RED   << ": " << colorName[RED] << endl;
  cout << BLUE  << ": " << colorName[BLUE] << endl;
  cout << GREEN << ": " << colorName[GREEN] << endl;
}

これでグローバル領域にもかけるようになりました。めでたしめでたし。

【追記】[C++] 列挙体 (enum) から名前(文字列)を取得するマクロ (2) を書きました。

はてなブックマーク - [C++] 列挙体 (enum) から名前(文字列)を取得するマクロ
Pocket

  • http://septuplebass.blog135.fc2.com/blog-entry-15.html sing a song of song

    [C++] 列挙体 (enum) から名前(文字列)を取得するマクロ (2)

    前回、列挙体 (enum) から名前(文字列)を取得するマクロについて書きました。前回のバージョンは
    enum color {RED=1, BLUE=2, GREEN=4};
    のような、値…