论坛首页 综合技术论坛

D语言与tpl之编译期动作

浏览 12572 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-03-05  
实际上因为C++的复杂性,以至于设计师很难有余裕在语法上再做创新。C++对于计算是够用的,但是对于描述性内容并不适当。MP其实很有用,只是受技术限制一般人想不到它的用处而已。
0 请登录后投票
   发表时间:2007-03-06  
hyf 写道
  template MixInAttr(T, char[] name){ 
     mixin(" T _" ~ name ~";");
     mixin(" T "~name~"(){ return _"~name~"; }");
     mixin(" void "~name~"(T v){ _"~name~" = v;}");
  }  


问几个问题,
我要MixInAttr!(int, ["myAttr1", "myAttr2", ..]); 
可以?

MixInAttr!(int, string, float);
得到 int item1; string item2; float item3;
可以?


完全可以,这有两个方面的问题,一是变参模板,二是对于模板参数是类型还是字符串的判断,这在D里面都是轻而易举。现在没有时间,有空我写个简单的例子。

hyf 写道

要真是那么追求code generate的能力,那就索性把整个D语言弄进编译时执行算了.

D语言目前正在把更多的东西加进编译时执行。D语言模板到现在已经和C++大不相同了,编译期计算也是为了解决以前编译时和执行时要写两套代码而作的。
hyf 写道

况且, 你展示的这些代码, 让我想起MACRO, C++不推荐使用MACRO就是因为它可以随意产生代码, 类型不安全, 可见性(可读)差.

D语言的mixin表达式要求参数字符串必须是一个完整的表达式,这和MACRO完全不同。MACRO也不是C++语言的一部分,如果你愿意,你也可以把C宏用在任何语言中,调用一个预处理器程序进行处理。这些东西都是强大的工具,会用就能用好,不会用不用它就是了。


hyf 写道

我觉得C++的MP设计非常适合,
在C++0x出来之后, 就可以更好的应付MP的复杂性. (现在已经够复杂了)
你可以去看看OpenC++, 他的元编程在语法树上做文章, 灵活性最强了.  是啥下场?

在这个世界上有好多工具可以做代码生成, (生成我还可以看到整个结果, 怎么不对一目了然)
在语言中做这种事情, 一来IDE智能提示废了, 而且没有编译期调试还玩不转.

D并不是做了这个就扔了那个,你不使用编译期执行,它还是一种类似C++的语言,一个项目中编译期执行的部分也不会太多。IDE的智能提示和调试这两种东西并不是人人都必须要用,编译期执行也还是可以写单元测试的。
0 请登录后投票
   发表时间:2007-03-06  
假设变参模板用TArgs表示
除非你有一种方法能把类型转化成字符串,实现
mixin(str(head(TArgs)) ~ " item" ~ i;

你说D语言的mixin表达式要求参数字符串必须是一个完整的表达式
head(TArgs) mixin("item" ~ i); 应该不行吧


等待你的例子。
0 请登录后投票
   发表时间:2007-03-07  

canonical 写道:
   最近D语言发布了1.0版,这是一个由编译器开发者所设计的编译语言,语法类似C++, 但是针对C++的弊病作了大量修正,并增加了很多现代特征,其中还是有一些新意在其中的。http://www.digitalmars.com/d/overview.html 我对其比较感兴趣的部分是D语言明确提出的编译期运行的概念。虽然C++让大众了解了meta programming技术,很多人因此认为meta programming的威力在于类型演算,但是在我看来meta programming的真正作用在于在编译期可以“动态”产生或调整代码结构。它依赖于类型是因为我们只能利用类型来承载一些额外信息, 这无疑也是对于类型的一种滥用。在D语言中template所接受的不仅仅是类型, 或者类型的类型,它可以是任何符号.
...

我很奇怪你为什么认为你下面列举的这些不是对类型的计算。meta-programming 所带来的新东西,就是我们可以通过一些类型或是编译时常量为参数,让编译器在编译的时候生成某些我们想要的类型。D 的 mixin 也好,C++ 的 Policy Based Design 和 Expression-Template 也好,都是这种新的表达能力的体现。

0 请登录后投票
   发表时间:2007-03-07  
hyf 写道
假设变参模板用TArgs表示
除非你有一种方法能把类型转化成字符串,实现
mixin(str(head(TArgs)) ~ " item" ~ i;

你说D语言的mixin表达式要求参数字符串必须是一个完整的表达式
head(TArgs) mixin("item" ~ i); 应该不行吧


等待你的例子。

出差在外,上网不方便,这边网吧连USB也禁了。已经完成了,加上空行和整个文件大概60行左右,包括一个简单的使用测试。

对字符串的判断似乎有问题:
template foo(Args ...){
    static if (is(Args[0] == char[]))
        ...
}

这个判断总是不能为真,不知是D的问题还是我使用上的问题,我改用匹配的方法:
template attrs(T, Args ...){
}

template attrs(T, char[] s, Args ...){
}

来进行区分,在里面调用一个递归的mixin模板,把各个成员生成出来。在这个mixin模板中,不断调用attr_accessor模板(我的blog中有),并递归地调用同一个模板,把剩余参数传递过去,递归是模板中使用非常频繁的技术。有一点要注意的是,递归mixin在D中是不允许的,但可以传递一个多余的整数模板参数避开这个问题。

并不需要把类型转成字符串,当然如果想做也能做成,参考pyd里面的实现代码,我的blog中有一篇讲了这个,只是不知道是否适用所有类型。

最后的调用方式如下:

class Foo{
  mixin attrs!(int, "foo");
  mixin attrs!(float, "bar");
  mixin attrs!(char, char[], float, short);
}

auto foo = new Foo;
foo.foo = 1;
foo.bar = 3.0f;
foo.item1 = 'c';
foo.item2 = "cc";
foo.item3 = 5.0f;
foo.item4 = 7;
0 请登录后投票
   发表时间:2007-03-07  

我还以为可以做到 mixin(typeof(T).fullname() ~ ...
qiezi 写道
template foo(Args ...){
    static if (is(Args[0] == char[]))
        ...
}

这个判断总是不能为真,不知是D的问题还是我使用上的问题,我改用匹配的方法:
template attrs(T, Args ...){
}

template attrs(T, char[] s, Args ...){
}

如果是手工枚举所有类型的话就没没法用于自定义类型了。
0 请登录后投票
   发表时间:2007-03-07  
hyf 写道

我还以为可以做到 mixin(typeof(T).fullname() ~ ...
qiezi 写道
template foo(Args ...){
    static if (is(Args[0] == char[]))
        ...
}

这个判断总是不能为真,不知是D的问题还是我使用上的问题,我改用匹配的方法:
template attrs(T, Args ...){
}

template attrs(T, char[] s, Args ...){
}

如果是手工枚举所有类型的话就没没法用于自定义类型了。


这个并不是手工枚举所有类型,而是判断第2个模板参数,如果是字符串值,就把它和后面的参数作为属性的名称。否则就把所有模板参数当作类型,依次定义item1, item2 ...

全部用字符串来生成是最差的做法,即便能够实现,实现起来也不方便。
0 请登录后投票
   发表时间:2007-03-07  
看了你attr_accessor模板,明白你的意思了
0 请登录后投票
   发表时间:2007-03-07  
to Elminster:
  meta programming对于C++而言是基于类型运算的,或者你把meta programming等价于C++中的类型运算。而在我的概念中,meta programming意味着对编译期运算能力的开发。在tpl语言中,编译期运算是个明确的概念,而它是符合一定的形式要求的,但是并不是类型运算,实际上在tpl中通过其他渠道来传递信息。
0 请登录后投票
   发表时间:2007-03-09  
qiezi 写道
hyf 写道
假设变参模板用TArgs表示
除非你有一种方法能把类型转化成字符串,实现
mixin(str(head(TArgs)) ~ " item" ~ i;

你说D语言的mixin表达式要求参数字符串必须是一个完整的表达式
head(TArgs) mixin("item" ~ i); 应该不行吧


等待你的例子。

出差在外,上网不方便,这边网吧连USB也禁了。已经完成了,加上空行和整个文件大概60行左右,包括一个简单的使用测试。

完整代码:
import std.stdio;
import std.metastrings;

private template attr_accessor(T, char[] name){
	mixin("
		private T _" ~ name ~ ";
		public T " ~ name ~ "(){
			return _" ~ name ~ ";
		}
		public void " ~ name ~ "(T v){
			_" ~ name ~ " = v;
		}"
	);
}

template attrs(T){
	mixin attr_accessor!(T, "item1");
}

template attrs(T, Args ...){
	mixin attrs_without_names!(0, T, Args);
}

template attrs(T, char[] s, Args ...){
	mixin attrs_with_names!(0, T, s, Args);
}

// 这个模板参数n是为了避免mixin递归错误。
private template attrs_with_names(int n, T, Args ...){
	static if (Args.length){
		mixin attr_accessor!(T, Args[0]);
		mixin attrs_with_names!(n + 1, T, Args[1..$]);
	}
}

private template attrs_without_names(int n, Args ...){
	static if (Args.length){
		mixin attr_accessor!(Args[0], "item" ~ ToString!(n + 1));
		mixin attrs_without_names!(n + 1, Args[1..$]);
	}
}

void main(){
	class Foo{
		mixin attrs!(int, "aaa");
		mixin attrs!(int, float, char[]);
	}

	auto foo = new Foo;
	foo.aaa = 1;
	foo.item1 = 3;
	foo.item2 = 5;
	foo.item3 = "abc";

	writefln(foo.aaa);
	writefln(foo.item1);
	writefln(foo.item2);
	writefln(foo.item3);
	writefln(typeid(typeof(foo.tupleof)));
}
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics