typelist.d

良い子のみんなーめたぷろぐらみんぐの時間だよー。とりあえず Typelist を書きました。参考書はもちろん Modern C++ Design 。

class NullType {}

class Typelist(H, T) {
  static H head;
  static T tail;
}

template Length(TL) {
  enum { value = 1 + Length!(typeof(TL.tail)).value }
}
template Length(TL : NullType) {
  enum { value = 0 }
}

template Pushfront(TL, T) {
  alias Typelist!(T, TL) value;
}

template TypeAt(TL, int i) {
  alias TypeAt!(typeof(TL.tail), i-1).value value;
}
template TypeAt(TL, int i : 0) {
  alias typeof(TL.head) value;
}

template Typelist1(T1) {
  alias Typelist!(T1, NullType) value;
}
template Typelist2(T1, T2) {
  alias Typelist!(T1, Typelist1!(T2).value) value;
}
template Typelist3(T1, T2, T3) {
  alias Typelist!(T1, Typelist2!(T2, T3).value) value;
}
template Typelist4(T1, T2, T3, T4) {
  alias Typelist!(T1, Typelist3!(T2, T3, T4).value) value;
}

unittest {
  alias Typelist1!(byte).value TL1;
  // it fails in Length. why?
//  alias Typelist2!(byte, short).value TL2;
  alias Typelist2!(short, byte).value TL2;
  // it fails in Length. why?
//  alias Typelist3!(byte, short, int).value TL3;
  alias Typelist3!(int, short, byte).value TL3;
  // it fails in Length. why?
//  alias Typelist4!(byte, short, int, long).value TL4;
  alias Typelist4!(long, int, short, byte).value TL4;

  assert(0 == Length!(NullType).value);
  assert(1 == Length!(TL1).value);
  assert(2 == Length!(TL2).value);
  assert(3 == Length!(TL3).value);
  assert(4 == Length!(TL4).value);

  alias Pushfront!(TL4, char[]).value TL5;
  assert(5 == Length!(TL5).value);

  TypeAt!(TL5, 0).value stringVal = "string";
  TypeAt!(TL5, 4).value byteVal = 'a';

  assert(1 == (TypeAt!(TL5, 4).value).sizeof);
  assert(2 == (TypeAt!(TL5, 3).value).sizeof);
  assert(4 == (TypeAt!(TL5, 2).value).sizeof);
  assert(8 == (TypeAt!(TL5, 1).value).sizeof);
}

メタカックロ電卓でもまた書くかなーと思ったけど、コンパイラのバグが多すぎてうまく行きませんでした。続きを書く気もなくなりました。暇な時にでも再チャレンジといきましょう。

色々コンパイラを落とすバグを見つけたけど、現状で報告しても嫌がらせにすぎないよねえ…

TypelistN (N は任意の整数) を書いてるとメタメタな何かが欲しくなりますね。そのへんは K.INABA さんがためになることを書いておられたなあ… MetaOCaml と Template Haskell か。学習キューに積んでおこう。

追記: Loki の Int2Type はそのまま作れるので整数のコンパイルタイムリストは実現できるわけですけど、 D言語の場合グローバル変数とかモジュールなんかも alias template parameter でリストにつっこめるわけです。それ使ってなんか面白いことできないもんかなと考えたけどどうも今一つ。

なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h