BTW:大概了解了一下D,很不错的语言。语法相比C++干净很多,基础很好。作为面向系统开发的语言,砍掉一部分不常用的特性是合理的举措。不过,一
旦成功,贪得无厌的程序员们,自然会尽其所能地将各自喜好的特性塞进语言,慢慢地又变成一个复杂的通用语言。
这种现象在C、Ada、C++,甚至现在的Java身上都发生过。一个混乱的世界。
D独创的"二元关键字" static if 和 static assert,几乎实现 C++0x concept
的效果。
在 2007-09-14五的 16:17 -0700,longshanksmo写道:
现在 D2.0 的设计, 很多是为了 fp 和并发编程考虑的, 这些如果也设计好了, 起
码在这些重要的点上,
不会出现太混乱的情形.
interface ICallable(Params...)
{
alias Params PT;
void opCall(Params args);
}
class Foo : ICallable!(int, int)
{
override void opCall(PT args)
{
}
}
当然了,这不是一个好例子,接口并不适合做模板,这里只是演示D有此能力。
更好的是使用模板值参数特化:
void func(T, bool checkConcept : true =
ArithmeticTypeConcept!(T))(T arg)
{
...
}
实际上D有更多的模式可供使用,已经实现的 D2.0Alpha 提供了静态反射
(__traits),配合 static assert 和 static if 可以更好地处理这些类型问
题。
在 2007-09-15六的 03:58 +0000,longshanksmo写道:
> 当然了,这不是一个好例子,接口并不适合做模板,这里只是演示D有此能力。
> 更好的是使用模板值参数特化:
>
> void func(T, bool checkConcept : true =
> ArithmeticTypeConcept!(T))(T arg)
> {
> ...
>
> }
> 当然了,这不是一个好例子,接口并不适合做模板,这里只是演示D有此能力。
> 更好的是使用模板值参数特化:
>
> void func(T, bool checkConcept : true =
> ArithmeticTypeConcept!(T))(T arg)
> {
> ...
>
> }
>
这是模板特化本身提供的static dispatch,可以算concept的模拟。形式上比C++更简洁,但本质是一样的。
concept提供了更"自然"和灵活的形式:
template<has_swap_mem T> //如果有swap成员,用swap成员交换
void swap(T& a, T& b)
{
a.swap(b);
}
template<has_exch_mem T>
requires !has_swap_mem<T>
void swap(T& a, T& b) //如果有exch成员,没有swap成员,用exch交换
{
a.exch(b);
}
template<typename T>
void swap(T& a, T& b) //其他的用临时变量交换
{
T t(a);
a=b;
b=t;
}
使用时,编译器根据T的特征寻找匹配的swap版本。
也可以使用concept_map,把拥有exch的类型"打扮"成has_swap_mem:
template<has_exch_mem T>
concept_map has_swap_mem<T> {
void swap(T& a, T& b) {
a.exch(b);
}
}
concept对于gp而言有非常重要的作用,否则,C++也不会在增加一个复杂的特性。concept对于D而言,差不多是现成的,C++已经指明了
方向。
void swap(T)(ref T x, ref T y)
{
static if(__traits(hasMember, T, "swap")) {
x.swap(y);
}
else if(__traits(hasMember, T, "exch")) {
x.exch(y);
}
else {
T tmp = x;
x = y;
y = tmp;
}
}
参考:
http://www.digitalmars.com/d/traits.html
- Oldrev
在 2007-09-15六的 06:02 +0000,longshanksmo写道:
这个不是合适,是ad-hoc。C++一度也是这样的,见boost.concept_check
import std.stdio;
template swap(T)
{
static if(__traits(hasMember, T, "swap"))
{
void swap(ref T x, ref T y) {
x.swap(y);
}
}
else static if(__traits(hasMember, T, "exch"))
{
void swap(ref T x, ref T y) {
x.exch(y);
}
}
else
{
void swap(ref T x, ref T y)
{
T tmp = x;
x = y;
y = tmp;
}
}
}
class Foo
{
void swap(Foo f)
{
writefln("Foo.swap");
}
}
class Bar
{
void exch(Bar b)
{
writefln("Bar.exch");
}
}
void main()
{
Foo f1 = new Foo;
Foo f2 = new Foo;
swap!(Foo)(f1, f2);
Bar b1 = new Bar;
Bar b2 = new Bar;
swap!(Bar)(b1, b2);
int x = 1, y = 2;
swap!(int)(x, y);
writefln("x=", x, ", y=", y);
}
- Oldrev
在 2007-09-15六的 14:58 +0800,lijie写道:
> 虽说D的实现更容易,但concept更清晰,毕竟是定义在函数形式上的而不是实
BTW: 说起 hasMember 这件事情, D2.0 里面一个 feature 和这个有交集, 不知道会如何处理.
D 2.0,
void func(int i){}
可以被当作 int 的 member 调用
int i;
i.func();
不知道在 traits 判断里面是否认为这个是 member ? (这个特性是为了容易扩展已经实现的类层次而设计的).
> > 方向。- Hide quoted text -
>
> - Show quoted text -
__traits(compiles) 能处理允许二者都合法的情况。
- Oldrev
在 2007-09-15六的 00:26 -0700,redsea写道:
清晰只是一方面。在concept下,swap的每一个实现都是独立的个体,这样也就突出了各种版本的独立性和特有性,对于代码的理解有所帮助。但这只
是一种心理上的"安慰"。更重要的是:
当我需要增加一种swap的实现,static if是否可行?是否意味着需要D允许合并两个不同函数或类的scope?
concept促使我们按照这样一个逻辑写模板:首先说明我这个模板是针对什么样的类型的。然后,再具体阐述这个模板的内容。对于函数模板而言,这更接
近算法理论的逻辑。
另外,就像pangba说的,first class的概念需要first class机制实现。concept和concept-map是
first class的机制,结果就是,first-class的机制往往是"多功能的"(我喜欢说"更接近于'道'"。:))。比
如,concept可以消除或简化一些traits的使用:
我首先利用concept和concept-map定义Integers和Floats分别代表整数和浮点数两个concept:
concept Integers<typename T>{...}
concept Floats<typename T>{...}
concept_map Integers<int>{};
concept_map Integers<long>{};
...
concept_map Floats<double>{};
concept_map Floats<float>{};
...
然后,我就可以使用了:
template<Integers T> T fun(T a, T b) {...}
template<Floats T> T fun(T a, T b) {...}
这些traits concept一次定义永远使用。(C++0x的标准库应该有这些东西,我没注意过)。
而我前一次回复中利用concept_map制作concept适配器,似乎还是没有办法替代的。
D 应该能模拟实现 concept 的所有功能,但是像 Pongba 说的,这不是 first-class,目前只能说是 "Not so pretty, but it works.",就跟 boost.concept_check 库差不多。
D 是社区驱动加仁慈专制的开发方式,如果真的有需要的话D也很快能实现这个东西,至少是在 C++0x 之前。
其实这个问题应该去问 Andrei Alexandrescu,呵呵
在 2007-09-15六的 08:07 +0000,longshanksmo写道:
1. 用 import, 不是 include
2. import 的时候, 是整个符号表引入, 不是重新进行词法语法分析
因此, 不会和实现 concept 有冲突.
Atry 写道: