d有趣的一元重载
import std.stdio;
struct S
{
int value;
alias opCall this;
this(int i) {
value = i;
}
alias opAssign = opCall;
@property opCall(int x) {
return value = x;
}
@property opCall() inout {
return value;
}
@property opOpAssign(string op)(int x) {
write(":"); // 在此前
mixin("return value"~op~"=x;");
}
// 不必: opUnary(string op)();
}
void main()
{
S a = S(10),
b = S(-1);
writeln(a + b); // 9
writeln(++a + b); // :10
a += 10; // :
assert(a == 21);
writeln("\n--");
writeln(-b); // 1
}
是的,有趣,我加了些注解:
import std.stdio;
struct S
{
int value;
说明允许此类型对象隐式转换为'int'('opCall'返回类型).
即,由于opCall返回'int',现在知道S对象可隐式代替int.调用opCall来确定值.
opCall允许像函数一样对待对象.如,当有"obj"时,可'obj()'.
注意:这让我有点困惑,因为下面有两个opCall定义,它们都返回"int".但是,因为下面这句,编译器选择无参的别名本,所以没有歧义.
alias opCall this;
this(int i) {
value = i;
}
你正在为opCall指定(opAssign)新名.编译器是否考虑opCall来赋值,或它在找正确的opAssign定义:
alias opAssign = opCall;
这是带'int'函数调用符,支持obj(42)等用法.
@property opCall(int x) {
return value = x;
}
这是空参调用opCall,支持obj()用法.
@property opCall() inout {
return value;
}
这是'obj+=42'等用法的操作符重载.
@property opOpAssign(string op)(int x) {
write(":");
mixin("return value"~op~"=x;");
}
// 不需要: opUnary(string op)();
}
void main()
{
/*这是普通构造对象*/
S a = S(10),//有个逗号
b = S(-1);
由于S未定义"+"操作,编译器会查找隐式转换,恰好是"int".以下表达式是两个整数的加法:10+(-1)
writeln(a + b); // 9
尽管S不支持++运算符,但D编译器会找到+=操作并用a+=1替换++.然后隐式转换a为'int',得到11.同样,表达式是11+(-1)的整数加法.
writeln(++a + b); // :10
/* 用opOpAssign. */
a += 10; // :
/* 结果有意义. */
assert(a == 21);
writeln("\n--");
writeln(-b); // 1
}
浙公网安备 33010602011771号