d使用d1的重载操作符
上个月发布的2.100
版本语言已完全删除旧重载
符号.但是,使用D出色的元编程功能
,可以编写插件模板
,来让D1
风格重载符号
继续工作.
对比D1
与D2
重载符号
重载
符号用来自定义
(如+和-)操作符.在D1
中,是用普通命名
函数,如加法opAdd
或乘法opMul
.示例,用整
来表示内部状态
的结构类型:
struct S {
int x;
S opAdd(S other) {
return S(x + other.x);
}
S opSub(S other) {
return S(x - other.x);
}
S opMul(S other) {
return S(x * other.x);
}
S opDiv(S other) {
assert(other.x != 0, "除零!");
return S(x / other.x);
}//后面简称为`四块代码`.
}
void main() {//后面简写为`主块代码`
S s1 = S(6);
S s2 = S(3);
assert(s1 + s2 == S( 9));
assert(s1 - s2 == S( 3));
assert(s1 * s2 == S(18));
assert(s1 / s2 == S( 2));
assert( s1 % s2 == S( 0));
assert((s1 | s2) == S( 7));
//...
}
太多重复代码.D2
改进了.
struct S {
int x;
S opBinary(string op)(S other) {
static if(op == "/" || op == "%")
assert(other.x != 0, "除零!");
return mixin("S(x ", op, " other.x)");
}
}
主块代码;
注意,仅有一个函数
(除法
符号略有
不同),且处理所有数学运算
!代码
更容易编写,更不容易出错
,也更简洁
.
别名符号
struct S {
int x;
四块代码;
alias opBinary(op : "+") = opAdd;
alias opBinary(op : "-") = opSub;
alias opBinary(op : "*") = opMul;
alias opBinary(op : "/") = opDiv;
//别名符号.
}
注意,在此使用了D元编程
很酷的特性.别名
是同名模板
,特化
了模板参数,并用模板约束
过滤.
插件模板
插件模板
更是强大.
为了完成它,制定三个规则
.
1,不关心
是否按D1
风格正确
编写操作符
.只要名字匹配
,就转发给他们
.也不担心重载
接受的类型或参数
,因为别名只是重写
名字.
2,该插件
必须放在类型
末尾,否则,编译器
可能不会分析整个类型
的成员(未来D版本
可能改变).
3,D
禁止插件和普通
函数间的重载
,且普通
函数优先.因此,不要定义有D2
风格符号的特定名(如opBinary
).如果想要D2
符号,则反之.总之,不要混用D1
和D2
.
在插件
模板中编写opAdd
声明,看看工作原理.
mixin template D1Ops() {
static if(__traits(hasMember, typeof(this), "opAdd"))
alias opBinary(op : "+") = opAdd;
//当有`opadd`时,别名此函数为左边.
}
这里有很多元代码
,我会一一解释.
插件模板
声明告诉编译器
,这是插件模板
.技术上,可插件
任意模板,但声明为插件模板
,则它只能用于插件
.
静如是条件为真时执行.
__traits(hasMember,T,"opAdd")
是仅当指定T
类型(这里插件
至相应构类型)有opAdd
成员函数时才为真的特殊条件
.最后,别名
和之前写的一样.
现在,如何在类型
中使用它呢?
struct S {
int x;
四块代码;
mixin D1Ops;
}
使用别名,可处理现有重载符号
问题.再借助静每一扩展.
mixin template D1Ops() {
static foreach(op, d1;
["+" : "opAdd", "-" : "opSub", "*" : "opMul", "/" : "opDiv","%" : "opMod"]) {
//static foreach编译时迭代普通运行时迭代元素.
static if(__traits(hasMember, typeof(this), d1))
alias opBinary(string s : op) = mixin(d1);//对每一个操作.
}
}
必须别名opBinary
至符号
.而不是串,因而用mixin(d1)
.这是相对新的功能
.旧版要用mixin
在整个别名
语句.最新的,相对就好看多了.最终代码:
mixin template D1Ops() {
static foreach(op, d1;
["+" : "opAdd", "-" : "opSub", "*" : "opMul", "/" : "opDiv","%" : "opMod"]) {
static if(__traits(hasMember, typeof(this), d1))
alias opBinary(string s : op) = mixin(d1);
}
}
struct S {
int x;
四块代码;
mixin D1Ops;
}
主块代码;
opMod
不在类
中.
其他D1风格符号
可,另加循环
来处理opUnary/opBinaryRight
,
还可嵌套
映射,或按映射
部分,来包含要别名的模板名
.opBinaryRight
和opBinary
,除了在in
上外,其余相同.用静每一
不易出错.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现