模板混入 2.014

[color=red](本章无版本差异)[/color]

[size=large]一个 模板混入 指的是从一个 模版声明 的过程体内 提取一个任意的声明 集合,并将它们插
入到当前的上下文中。

模板混入:
mixin 模板标识符 ;
mixin 模板标识符 混入标识符 ;
mixin 模板标识符 !(模板参数列表 ) ;
mixin 模板标识符 !(模板参数列表 ) 混入标识符 ;

混入标识符:
标识符
模版混入 可以出现在模块、类、结构、联合的声明列表中,并且可以做为语句。模板标识
符 是一个 模版声明。如果 模版声明 没有参数,就可以使用不带 !(模版参数列表) 的混入
形式。

不像模板具现化,模板混入的过程体在混入 所在的作用域内 计算,而不是在定义模板声明的
地方。

这类似于使用剪切和粘贴将模版的过程体插入混入的位置。这对注入参数化的‘样板
文件’是有用的,同时对创建模板化 嵌套函数 也很有用,而正常情况下是不可能具 现化嵌套函数的。

template Foo()
{
int x = 5;
}

mixin Foo;
struct Bar
{
mixin Foo;
}

void test()
{
writefln("x = %d", x); // 输出 5
{ Bar b;
int x = 3;
writefln("b.x = %d", b.x); // 输出 5
writefln("x = %d", x); // 输出 3
{
mixin Foo;
writefln("x = %d", x); // 输出 5
x = 4;
writefln("x = %d", x); // 输出 4
}
writefln("x = %d", x); // 输出 3
}
writefln("x = %d", x); // 输出 5
}

混入可以被参数化:

template Foo(T)
{
T x = 5;
}
mixin Foo!(int); // 创建类型为 int 的 x

混入可以可以[color=red]为类添加虚函数[/color]:

template Foo()
{
void func() { writefln("Foo.func()"); }
}

class Bar
{
mixin Foo;
}

class Code : Bar
{
void func() { writefln("Code.func()"); }
}

void test()
{
Bar b = new Bar();
b.func(); // 调用 Foo.func()
b = new Code();
b.func(); // 调用 Code.func()
}

混入在它们出现的地方被求值,而不是在模板声明的地方:

int y = 3;
template Foo()
{
int abc() { return y; }
}

void test()
{
int y = 8;
mixin Foo; // 使用的是局部的 y ,而不是全局的 y
assert(abc() == 8);
}

混入可以使用别名参数来参数化符号:
template Foo(alias b)
{
int abc() { return b; }
}

void test()
{
int y = 8;
mixin Foo!(y);
assert(abc() == 8);
}

这个例子使用了一个混入来为任意语句实现一个泛型 Duff's Device(在这里,那个语句采用粗体表示)。在生成一个嵌套函数的同时也生成了一个委托文字量,他们会通过编译器内
联:

template duffs_device(alias id1, alias id2, alias s)
{
void duff_loop()
{
if (id1 < id2)
{
typeof(id1) n = (id2 - id1 + 7) / 8;
switch ((id2 - id1) % 8)
{
case 0: do { s();
case 7: s();
case 6: s();
case 5: s();
case 4: s();
case 3: s();
case 2: s();
case 1: s();
} while (--n > 0);
}
}
}
}

void foo() { writefln("foo"); }

void test()
{
int i = 1;
int j = 11;
mixin duffs_device!(i, j, delegate { foo(); } );
duff_loop(); // 执行 foo() 10 次
}


18.1 混入作用域

混入中的声明被‘导入’到周围的作用域中。如果混入和其周围的作用域中有相同的名字,
周围的作用域中的声明将覆盖混入中的那个声明:

int x = 3;
template Foo()
{
int x = 5;
int y = 5;
}

mixin Foo;
int y = 3;
void test()
{
writefln("x = %d", x); // 输出 3
writefln("y = %d", y); // 输出 3
}

如果两个不同的混入被放入同一个作用域,并且他们中定义了同名的声明,就会出现模棱两
可的错误:

template Foo()
{
int x = 5;
void func(int x) { }
}

template Bar()
{
int x = 4;
void func() { }
}

mixin Foo;
mixin Bar;

void test()
{
writefln("x = %d", x); // 错误,x 有歧义
func(); // 错误,func 有歧义
}

对 func() 的调用有歧义,因为 Foo.func 和 Bar.func 在不同的作用域里。

如果一个混入[color=red]有 混入标识符,它就可以用来消除歧义:[/color]

int x = 6;
template Foo()
{
int x = 5;
int y = 7;
void func() { }
}

template Bar()
{
int x = 4;
void func() { }
}

mixin Foo F;
mixin Bar B;

void test()
{
writefln("y = %d", y); // 输出 7
writefln("x = %d", x); // 输出 6
writefln("F.x = %d", F.x); // 输出 5
writefln("B.x = %d", B.x); // 输出 4
F.func(); // 调用 Foo.func
B.func(); // 调用 Bar.func
}

别名声明可以被用来将声明在不同混入里的函数重载在一起:

template Foo()
{
void func(int x) { }
}
template Bar()
{
void func() { }
}

mixin Foo!() F;
mixin Bar!() B;
alias F.func func;
alias B.func func;

void main()
{
func(); // 调用 B.func
func(1); // 调用 F.func
}

一个混入有它自己的作用域,即使一个声明被另一个封闭的声明所重写也一样:

int x = 4;
template Foo()
{
int x = 5;
int bar() { return x; }
}

mixin Foo;
void test()
{
writefln("x = %d", x); // 输出 4
writefln("bar() = %d", bar()); // 输出 5
}

[/size]


。。。。。。。。。。。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值