鍋あり谷あり

テーマを決めずに適当に書いています。

#include と #define を組み合わせる

d:id:tt_clown:20100904:1283587136
で話題になっていたので、ちょっと変だと思われがちな include の使い方をひとつ。

// corr.h
MAP( SOME_ID_DOG, ANOTHER_ID_INU )
MAP( SOME_ID_CAT, ANOTHER_ID_NEKO )
MAP( SOME_ID_FOX, ANOTHER_ID_KITSUNE )
MAP( SOME_ID_ELEP, ANOTHER_ID_ZOU )
MAP( SOME_ID_MOUSE, ANOTHER_ID_NEZU )

としておいて、

int some_to_another( int some_id )
{
  #define MAP( x, y )  case x: return y;
  swtich( some_id )
  {
    #include "corr.h"
  }
  #undef MAP
  throw UnexpectedSomeIdException();
}

int another_to_some( int another_id )
{
  #define MAP( x, y )  case y: return x;
  swtich( another_id )
  {
    #include "corr.h"
  }
  #undef MAP
  throw UnexpectedAnotherIdException();
}

とすると、switch-case でコンパイル時生成の双方向マップを作ることができる。
たぶん、コンパイラがよろしくやってくれるので、それなりに速いのではないかと思う。初期化不要だし。

実際に使うときは、「MAP」のようなぶつかりやすい名前は避けるけど、これは例ということで。

あと、魔術的な include の使い方というと、

  • 自分で自分を include する(上記の corr.h と関数本体を同じファイルに書くとか)
  • C言語で template の代用として使う(マクロを定義してから #include する)

なんかもありがち。

特に自己 include は魔術的になりやすく、ひとの書いたソースで遭遇すると、なんかぐっとくる感じがする。

あんまり見ないけど。