D语言中的混入(Mixin)

混入

混入(Mixins) 意味着用不同的编程语言表达的不同的事物。 在D中,一个混入从一个 模版声明 的过程体内提取一个任意的声明集合,并将它们插入到当前的上下文中。 
	模板混入:
		mixin 模板标志符 ;
		mixin 模板标志符 混入标志符 ;
		mixin 模板标志符 !( 模版参数列表 ) ;
		mixin 模板标志符 !( 模版参数列表 ) 混入标志符 ;

	混入标志符:
		标志符
	TemplateMixin:
		mixin TemplateIdentifier ;
		mixin TemplateIdentifier MixinIdentifier ;
		mixin TemplateIdentifier !( TemplateArgumentList ) ;
		mixin TemplateIdentifier !( TemplateArgumentList ) MixinIdentifier ;

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

不像模板具现化,模板混入的过程体在混入所在的作用域内计算,而不是在定义模板声明的地方。这等价于使用剪切和粘贴将模版的过程体插入混入的位置。这对注入参数化的‘样板文件’是有用的,同时对创建模板化嵌套函数也很有用,而正常情况下是不可能具现化嵌套函数的。

	template Foo()
	{
	    int x = 5;
	}

	mixin Foo;

	struct Bar
	{
	    mixin Foo;
	}

	void test()
	{
	    printf("x = %d/n", x);		// 打印出 5
	    {
		Bar b;
		int x = 3;

		printf("b.x = %d/n", b.x);	// 打印出 5
		printf("x = %d/n", x);	// 打印出 3
		{
		    mixin Foo;
		    printf("x = %d/n", x);	// 打印出 5
		    x = 4;
		    printf("x = %d/n", x);	// 打印出 4
		}
		printf("x = %d/n", x);	// 打印出 3
	    }
	    printf("x = %d/n", x);		// 打印出 5
	}
	
混入可以被参数化:
	template Foo(T)
	{
	    T x = 5;
	}

	mixin Foo!(int);		// 创建类型为 int 的 x
	
混入可以可以为类添加虚函数:
	template Foo()
	{
	    void func() { printf("Foo.func()/n"); }
	}

	class Bar
	{
	    mixin Foo;
	}

	class Code : Bar
	{
	    void func() { printf("Code.func()/n"); }
	}

	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() { printf("foo/n"); }

	void test()
	{
	    int i = 1;
	    int j = 11;

	    mixin duffs_device!(i, j, delegate { foo(); } );
	    duff_loop();		// 执行 foo() 10 次
	}
	

混入作用域

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

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

	mixin Foo;
	int y = 3;

	void test()
	{
	    printf("x = %d/n", x);	// 打印出 3
	    printf("y = %d/n", y);	// 打印出 3
	}
	
如果两个不同的混入被放入同一个作用域,并且他们中定义了同名的声明,就会出现模棱两可的错误:

   template Foo()
   {
       int x = 5;
   }

   template Bar()
   {
       int x = 4;
   }

   mixin Foo;
   mixin Bar;

   void test()
   {
       printf("x = %d/n", x); // 错误,x 模棱两可
   }

如果一个混入中有 混入标志符 ,它可以用来消除歧义:
	int x = 6;

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

	template Bar()
	{
	    int x = 4;
	}

	mixin Foo F;
	mixin Bar B;

	void test()
	{
	    printf("y = %d/n", y);		// 打印出 7
	    printf("x = %d/n", x);		// 打印出 6
	    printf("F.x = %d/n", F.x);	// 打印出 5
	    printf("B.x = %d/n", B.x);	// 打印出 4
	}
	
混入有其自身的作用域,尽管声明会被外围的声明覆盖:
	int x = 4;

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

	mixin Foo;

	void test()
	{
	    printf("x = %d/n", x);		// 打印出 4
	    printf("bar() = %d/n", bar());	// 打印出 5
	}
	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值