锁定老帖子 主题:D语言与tpl之编译期动作
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-03-05
实际上因为C++的复杂性,以至于设计师很难有余裕在语法上再做创新。C++对于计算是够用的,但是对于描述性内容并不适当。MP其实很有用,只是受技术限制一般人想不到它的用处而已。
|
|
返回顶楼 | |
发表时间: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的智能提示和调试这两种东西并不是人人都必须要用,编译期执行也还是可以写单元测试的。 |
|
返回顶楼 | |
发表时间:2007-03-06
假设变参模板用TArgs表示
除非你有一种方法能把类型转化成字符串,实现 mixin(str(head(TArgs)) ~ " item" ~ i; 你说D语言的mixin表达式要求参数字符串必须是一个完整的表达式 head(TArgs) mixin("item" ~ i); 应该不行吧 等待你的例子。 |
|
返回顶楼 | |
发表时间: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 也好,都是这种新的表达能力的体现。 |
|
返回顶楼 | |
发表时间: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; |
|
返回顶楼 | |
发表时间: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 ...){ } 如果是手工枚举所有类型的话就没没法用于自定义类型了。 |
|
返回顶楼 | |
发表时间: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 ... 全部用字符串来生成是最差的做法,即便能够实现,实现起来也不方便。 |
|
返回顶楼 | |
发表时间:2007-03-07
看了你attr_accessor模板,明白你的意思了
|
|
返回顶楼 | |
发表时间:2007-03-07
to Elminster:
meta programming对于C++而言是基于类型运算的,或者你把meta programming等价于C++中的类型运算。而在我的概念中,meta programming意味着对编译期运算能力的开发。在tpl语言中,编译期运算是个明确的概念,而它是符合一定的形式要求的,但是并不是类型运算,实际上在tpl中通过其他渠道来传递信息。 |
|
返回顶楼 | |
发表时间: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))); } |
|
返回顶楼 | |