データとかアルゴリズムとかポリシーとかの分離とか

最近の

http://d.hatena.ne.jp/w_o/20060613#p2

のあたりは私も色々考えたことがあるのですが、おっしゃってる通り C++ だと template の限界が来るのと、あと、コンパイルおっせー、っていう理由でまぁ色々 GameObj から継承したらいいじゃんとかそういう日和りが起きてきます。

というかゲームと STL のデータとアルゴリズムの分離チックな template の用法は相性が良さそうでどうも悪いというか…

D だとどう見てもマクロですありがとうございましたな mixin を使うのが私的に好みです。普通、クラスが決まればアルゴリズムは一つに決まりますし。 Web に上がってる範囲だと、 PSYNO の objspec.d あたりがたぶん wo さんがやりたいことを D でやってみたチックな感じじゃないかと(ぜんぜん徹底されてませんが)。

template getMemberDX() {
    typeof(dx) getMemberDX() {
        return dx;
    }
}
template getIdoukyoriDX() {
    typeof(idou_kyori_x()) getMemberDX() {
        return idou_kyori_x();
    }
}

class Meteorite{
    mixin getMemberDX;
    float x; float y; float dx; float dy;
}
class SpaceShip{
    mixin getIdoukyoriDX;
    float x; float y; int dx_; int dy_;
    int idou_kyori_x() {
        return dx_;
    }
}

int main() {
    Meteorite m = new Meteorite();
    SpaceShip s = new SpaceShip();
    m.dx = 1;
    s.dx_ = 2;
    printf("%f %d\n", m.getMemberDX(), s.getMemberDX());
    return 0;
}

typeof あるんで template でもできるかと思います。ていうかどうせ C++0x には入るでしょうし、どうせ GCC なんで、 typeof 使っちゃえ、という話も。

あと C++ だとあとは多重継承という武器もあるのですが、ヘタに型チェックとかやられてしまうのがあまり嬉しくないというか、マクロでいいよもう、というか。

パスカルの三角形

が流行っているらしいのですいつの話だ。

D で書きました。残念ながらコンパイルが通りませんが結果オーライ。改行とかできないのでぜんぜん三角形になりません。

i@u ~/test/d> dmd pascal.d
pascal.d(55): static assert  (0) is false, "[ 1 ] [ 1 1 ] [ 1 2 1 ] [ 1 3 3 1 ] 
[ 1 4 6 4 1 ] [ 1 5 10 10 5 1 ] [ 1 6 15 20 15 6 1 ] "

MPL とか無くても割となんとかなるなーという感でした。以下コード。

template itoa_(int n) {
    template digit(long n) { const char [] digit = "0123456789"[n..n+1]; }
    static if (n<0)  const char [] s = "-" ~ itoa_!(-n).s;
    else static if (n<10L) const char [] s = digit!(n);
    else const char [] s = itoa_!(n/10L).s ~ digit!(n%10L);
}

template itoa(long n) {
    const char [] itoa = itoa_!(n).s;
}

class list {}

template head(T) { const int head = T.sizeof/typeof(T[0]).sizeof; }
template tail(T) { alias typeof(T[0]) tail; }

template ltoa_(T) {
    const char[] ltoa_ = ltoa_!(tail!(T)) ~ itoa!(head!(T)) ~ " ";
}
template ltoa_(T : list) {
    const char[] ltoa_ = "";
}
template ltoa(T) {
    const char[] ltoa = "[ " ~ ltoa_!(T) ~ "]";
}

template pascal_line2(int h, V) {
    alias pascal_line!(V)[h+head!(V)] pascal_line2;
}
template pascal_line2(int h, V : list) {
    alias pascal_line!(V)[h] pascal_line2;
}
template pascal_line(T) {
    alias pascal_line2!(head!(T), tail!(T)) pascal_line;
}
template pascal_line(T : list) {
    alias list pascal_line;
}

template pascal_(T, int n) {
    alias pascal_line!(T)[1] l;
    const char[] r = ltoa!(l) ~ " " ~ pascal_!(l, n-1).r;
}
template pascal_(T, int n : 0) {
    const char[] r = "";
}

template pascal(int n) {
    const char[] r = pascal_!(list, n).r;
    static assert(false, r);
}

pascal!(7) p;

参考文献。

itoa: http://www.digitalmars.com/d/archives/digitalmars/D/29734.html

list: http://www.kmonos.net/wlog/35.php#_0043040201

あ、ちなみに static-array は 7次元が限度だそうです。シンボルは以下のような感じになってました

00000000 D _D6pascal46__T7pascal_TG1G6G15G20G15G6G1C6pascal4listVi0Z1rAa

デマングルすると、

00000000 D char[] pascal.__T5ltoa!(typedef class pascal.list[1][6][15][20][15][6][1]).ltoa!()

ちゃんと答えが入ってますな。

データとかの分離とかのアルゴリズムとかの

alias template で以下のように書く方がステキでした。

template getDX(alias A) {
    static if (is (typeof(A()))) alias typeof(A()) rettype;
    else alias typeof(A) rettype;
    rettype getMemberDX() {
        return A;
    }
}

class Meteorite{
    float x; float y; float dx; float dy;
    mixin getDX!(dx);
}
class SpaceShip{
    float x; float y; int dx_; int dy_;
    int idou_kyori_x() {
        return dx_;
    }
    mixin getDX!(idou_kyori_x);
}

int main() {
    Meteorite m = new Meteorite();
    SpaceShip s = new SpaceShip();
    m.dx = 1;
    s.dx_ = 2;
    printf("%f %d\n", m.getMemberDX(), s.getMemberDX());
    return 0;
}
なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h