2

Dのコンパイル時の評価についてもう少し学び、そのテンプレート、ミックスイン、属性などがすべてどのように機能するかを理解しようとしています。私が試してみたいことの1つは、クラスのメンバーをデータベースからシリアル化可能またはロード可能としてマークするためのエレガントな方法を見つけることです。以下の例では、インスタンスの読み取りまたは(後で)シリアル化するときに使用するメンバーをリストするタプルを作成しました。

私の最初の質問は、これは下にあるタプルの適切な使用法ですか?次に、もしそうなら、関連するメンバー変数に割り当てたユーザー定義の属性を使用して、コンパイル時にこのタプルを自動的に生成する方法はありますか?http://dlang.org/attribute.htmlhttp://dlang.org/phobos/std_traits.htmlなどのさまざまなドキュメントページを調べましたが、それらを適切に使用する方法がわからないようです。この目的(つまり、クラスのメンバーをループして、目的の属性を持つ変数を判別する)。また、属性がどのように使用されるかについて完全に間違った考えを持っているかどうかもよくわかりません。これを実行するための最良の方法に関する提案をいただければ幸いです。

enum ENCODABLE = 1;
alias string[string] Row;
template Tuple (T...) { alias T Tuple; }

class A {
    @(ENCODABLE) string name;
    @(ENCODABLE) int x;
    int* p;

    alias Tuple!("name","x") encodables;

    this(Row row) {
        foreach (var; encodables) {
            __traits(getMember, this, var) = to!(typeof(__traits(getMember, this, var)))(row[var]);
        }
    }
}

void main() {
    Row row = ["name":"Asdf", "x":"120"]; // Simulated database row
    auto a = new A(row);
    writefln("%s,%d,%d", a.name, a.x, a.p); // Asdf,120,null
}
4

2 に答える 2

1

これはあまり答えではありませんが、独自のヘルパーテンプレートを定義し、構造体をUDAとして使用することでそれらを使用しました(値はパラメーターを示します)。ヘルパーテンプレートは次のとおりです。

https://github.com/Cyber​​Shadow/ae/blob/master/utils/meta.d#L133

ここでは、JSONシリアライザー/アンシリアライザーのJSONフィールドをオーバーライドできるようにするために使用されます。

https://github.com/Cyber​​Shadow/ae/blob/master/utils/json.d#L505

于 2013-01-09T15:33:53.870 に答える
0

私はそれを次のコードで動作させることができました、そしてサイバーシャドウの答えで提供されたコードに基づいたisValueInTupleテンプレートからの少しの助け。それはまだ少し不格好に感じますが、仕事を成し遂げているようです。テンプレートの性質に対して恐ろしいことをしている場合は、コメント/批評を歓迎します!

enum {
    ENCODABLE = "ENCODABLE",
};
alias string[string] Row;
template Tuple(T...) { alias T Tuple; }
template isValueInTuple(string s, T...) {
    static if (T.length == 0) {
        enum bool isValueInTuple = false;
    } else static if (T.length == 1) {
        static if (is(typeof(T[0]) == typeof(s))) {
            enum bool isValueInTuple = T[0] == s;
        } else {
            enum bool isValueInTuple = false;
        }
    } else {
        enum bool isValueInTuple = isValueInTuple!(s, T[0]) || isValueInTuple!(s, T[1..$]);
    }
}
template GenEncodables(U) {
    string GenEncodables() {
        string ret = "alias Tuple!(";
        int fn = 0;
        foreach (index, field; __traits(allMembers, U)) {
            static if (field != "Monitor") { // better way to avoid compilation errors here?
                static if (isAssignable!(typeof(mixin(U.stringof~"."~field)))) {
                    static if (isValueInTuple!(ENCODABLE, __traits(getAttributes, mixin(U.stringof~"."~field)))) {
                        if (fn++)
                            ret ~= ",";
                        ret ~= `"`~field~`"`;
                    }
                }
            }
        }
        ret ~= ") encodables;";
        return ret;
    }
}
mixin template Encodables() {
    mixin(GenEncodables!(typeof(this)));
}


class A {
    @ENCODABLE string name;
    @ENCODABLE int x;
    int *p;

    this() {}

    mixin Encodables; // must come after this() definition, apparently!

    this(Row row) {
        foreach (var; encodables) {
            pragma(msg, "Reading parameter "~var~" from row");
            __traits(getMember, this, var) = to!(typeof(__traits(getMember, this, var)))(row[var]);
        }
    }
}
于 2013-01-17T16:21:15.940 に答える