48用d编程插件

模板可以生成函数,结构,联,类,接口和任何其他合法的D代码.
模板插件插入模板实例,如下:

 mixin a_template!(template_parameters)
//
mixin template EdgeArrayFeature(T, size_t count) {
//这里定义`模板插件`
    T[count] edges;

    void setEdge(size_t index, T edge) {
        edges[index] = edge;
    }

    void printEdges() {
        writeln("The edges:");

        foreach (i, edge; edges) {
            writef("%s:%s ", i, edge);
        }

        writeln();
    }
}

然后将插件实例化至放插件的地方.

 mixin EdgeArrayFeature!(int, 2);//这样,在此插入.
//或这样
struct Line {
     mixin EdgeArrayFeature!(int, 2);
}

或这样

struct Point {
    int x;
    int y;
}

void main() {
    mixin EdgeArrayFeature!(Point, 5);

    setEdge(3, Point(3, 3));
    printEdges();
}

模板插件必须用本地导入,避免在导入点,找不到模块.

module a;

mixin template A(T) {
    //A,放在此处也可以,在插件的域中.
    string a() {
        import std.string;//必须放在内部
//否则,放在外部,模板插件实例化后,可能编译不过
        T[] array;
        // ...
        return format("%(%s, %)", array);
    }
}

找到自己的类型this.

mixin template MyMixin(T) {
    void foo(this MixingType)() {//自己类型
        import std.stdio;
        writefln("插件所在的实际类型: %s",MixingType.stringof);
    }
}

struct MyStruct {
    mixin MyMixin!(int);
}

void main() {
    auto a = MyStruct();
    a.foo();
}

除了插件模板,还有插件串,D又一个非常强大的特征.
mixin(compile_time_generated_string)

import std.stdio;

void main() {
    mixin (`writeln("hello world");`);
}

厉害在于,代码是编译时生成.

import std.stdio;

string printStatement(string message) {
    return `writeln("` ~ message ~ `");`;
}

void main() {
    mixin (printStatement("hello world"));
    mixin (printStatement("hi world"));
}

插件名字歧义:

import std.stdio;

template Templ() {
    int i;

    void print() {
        writeln(i);  //模板中的i
    }
}

void main() {
    int i;
    mixin Templ;

    i = 42;      // 主中的i
    writeln(i);  // 主中
    print();     // 模板中
}

多插件名冲突,解决:

    mixin Templ A;    // Defines A.i
    mixin Templ B;    // Defines B.i
//再定义一个名字.

    A.i = 42;      

串插件没有名字空间.

void main() {
    mixin ("int i;");
    mixin ("int i;");    // 编译错误

    i = 42;
}

一种简单消歧方法,把串插件搞成模板插件,然后消歧:

template Templatize(string str) {
    mixin (str);
}

void main() {
    mixin Templatize!("int i;") A;//靠的是这两句
    mixin Templatize!("int i;") B;//靠的是这两句
    A.i = 42;//消歧
}

串插件在操作符重载时,很有用.操作符重载定义为模板也是为了方便生成代码.
串插件用在析构器中:

import std.stdio;

mixin template Foo() {
    ~this() {
        writeln("Destructor mixed-in by Foo");
    }
}

mixin template Bar() {
    ~this() {
        writeln("Destructor mixed-in by Bar");
    }
}

struct S {
    ~this() {
        writeln("Actual destructor");
    }
    mixin Foo;
    mixin Bar;
}

void main() {
    auto s = S();
}

析构顺序与插件调用顺序相反.
这种方式允许插入不同的资源至一个类型,资源自己在不同插件模板元中清理自己.然后使用者调用相应析构插件.
由于写本书时的漏洞,析构器目前不能这样.但当前(2020)不确定.
此外,串插件的析构器确实与类型析构器冲突了.

int[] filter(string predicate)(in int[] numbers) {
    int[] result;

    foreach (number; numbers) {
        if (mixin (predicate)) {
            result ~= number;
        }
    }

    return result;
}

上面的可以用λ来写,更方便.在没有λ时很流行.
这样使用:

    int[] numbers = [ 1, 8, 6, -2, 10 ];
    int[] chosen = filter!"number < 7"(numbers);

是不是,太暴力了.且名字必须匹配.

发布了440 篇原创文章 · 获赞 29 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/fqbqrr/article/details/104590066
今日推荐