読者です 読者をやめる 読者になる 読者になる

【D言語】無名列挙体のメンバを取得したい【enum】

最近、グローバルに定義された無名列挙体のメンバをコンパイル時に取得したいということがありました。 しかし、どうにもうまく行きませんでした・・・

無名列挙体のメンバが取得できると・・・


foreachで回すことができて、とって便利です。 無名でなければ、__traits(allMembers, type) で簡単に文字列として取得できますし、 std.traits.EnumMembersで簡単に取得できます。


import std.traits;
enum Hoge{
    a, b, c, d
}

void main(){
    int[] ary = new int[](EnumMembers!Hoge.length);
    foreach(i, elem; EnumMembers!Hoge){
        ary[elem] = i;
    }
    ary[Hoge.a].writeln(); // 0
    ary[Hoge.d].writeln(); // 3
}

当然、無名列挙体だと、指定する型が無いので上記の方法が使えません。

__traitsのallMembersにモジュール名を渡してみる


これでうまく行けば御の字だったのですが・・・


module hoge;
import std.stdio;

enum{
    a, b, c, d
}

void main(){
    pragma(msg, __traits(allMembers, hoge)); // tuple("object", "std", "main")
}

見事に取得出ていません。

片っ端から __traits(compiles, member) を使って調べていく


もちろん、この方法ならできるのですが、スマートじゃないですよね・・・ 探す文字列の長さの上限によっては、コンパイル時間がBoostしたり、dmd先生が死んでしまったりします。

結論


多分無理です。 無名列挙体なんてforeachで走査する際、とっても扱いづらいので、 ライブラリなどを作る際は、できるだけ使わないでください。 お願いします。

この記事とはあまり関係ありませんが、Phobosスタイルでは、関数の動作にバリエーションを持たせるときは、名前付き列挙体を使います。

担当:美馬(名前付き列挙体に変更するプルリクエストを送りつけたい・・・)