Defining Scoped Enumerations with Human-readable Outputs

出力がちょっとだけホモ・サピエンスに優しい scoped enumeration を定義するだけのカンタンなマクロを作ったような気がする. GCC 4.6.1 -std=c++0x で動いたような気もする.

#include <iostream>

// 第1引数に enumeration の identifier (enum-name) を
// 第2引数以下に enumerator-definition を指定すること.
// 指定できる enumerator-definition は可変長で最大255個(のはず).
CRYOLITE_DECL_ENUM(Color, red, yellow, green, blue, white, black)

int main()
{
  std::cout << Color::red << std::endl;    // => "red"
  std::cout << Color::yellow << std::endl; // => "yellow"
  std::cout << Color::green << std::endl;  // => "green"
  std::cout << Color::blue << std::endl;   // => "blue"
  std::cout << Color::white << std::endl;  // => "white"
  std::cout << Color::black << std::endl;  // => "black"
}

出力がちょっとだけホモ・サピエンスに優しい以外は scoped enumeration とほとんど同じ.「第2引数以下に enumerator-definition を指定すること」って書いてるんだから, enumerator-definition のうち constant-expression の部分も書けないといけませんがなぜか書けちゃうようにできてる.ふしぎふしぎ.

#include <iostream>

// usamimi は 178
CRYOLITE_DECL_ENUM(KemonoMimi, inumimi, nekomimi, usamimi = 178, kitsunemimi)

int main()
{
  std::cout << KemonoMimi::inumimi << std::endl;     // => "inumimi"
  std::cout << KemonoMimi::nekomimi << std::endl;    // => "nekomimi"
  std::cout << KemonoMimi::usamimi << std::endl;     // => "usamimi"
  std::cout << KemonoMimi::kitsunemimi << std::endl; // => "kitsunemimi"

  std::cout << static_cast<int>(KemonoMimi::usamimi) << std::endl; // => "178"
}

まー,所詮マクロだし, constant-expression の部分に parenthesized じゃないむき出しの comma があると死にますさようなら.ちなみに上の例と下の例とで enumerator-definition の数を変えて可変長な感じを強調しているつもりだけど微妙に強調できてないっぽいのが悲しいですね? 見た目にこだわって可変長マクロと闘うようなことさえしなければ,実装コードにあるような数字の羅列を書かなくて済むわ, __VA_ARGS__ の展開タイミングに悩まなくて済むわ,いろいろ楽できるものを…….

以下,上記の CRYOLITE_DECL_ENUM というマクロの機能を実現するための実装っぽい何か.これ, GCC 以外でマクロの展開順序という超じゃじゃ馬娘を御しきるのが大変じゃないでしょうか.知らんけど? あ, 'a'-'z', 'A'-'Z' の連続を仮定してるの誰かなんとかしといてください私もう寝ますんで.

続きを読む