48用d编程插件
模板可以生成函数,结构,联,类,接口和任何其他合法的D代码
.
模板插件
插入模板实例,如下:
mixin a_template!(template_parameters)
//
mixin template EdgeArrayFeature(T, size_t count) {
//这里定义`模板插件`
T[count] edges;
void setEdge(size_t index, T edge) {
edges[index] = edge;
}
void printEdges() {
writeln("The edges:");
foreach (i, edge; edges) {
writef("%s:%s ", i, edge);
}
writeln();
}
}
然后将插件实例化至放插件的地方.
mixin EdgeArrayFeature!(int, 2);//这样,在此插入.
//或这样
struct Line {
mixin EdgeArrayFeature!(int, 2);
}
或这样
struct Point {
int x;
int y;
}
void main() {
mixin EdgeArrayFeature!(Point, 5);
setEdge(3, Point(3, 3));
printEdges();
}
模板插件必须用本地导入
,避免在导入点,找不到模块.
module a;
mixin template A(T) {
//A,放在此处也可以,在插件的域中.
string a() {
import std.string;//必须放在内部
//否则,放在外部,模板插件实例化后,可能编译不过
T[] array;
// ...
return format("%(%s, %)", array);
}
}
找到自己的类型this
.
mixin template MyMixin(T) {
void foo(this MixingType)() {//自己类型
import std.stdio;
writefln("插件所在的实际类型: %s",MixingType.stringof);
}
}
struct MyStruct {
mixin MyMixin!(int);
}
void main() {
auto a = MyStruct();
a.foo();
}
除了插件模板
,还有插件串
,D又一个非常强大的特征.
mixin(compile_time_generated_string)
import std.stdio;
void main() {
mixin (`writeln("hello world");`);
}
厉害在于,代码是编译时生成.
import std.stdio;
string printStatement(string message) {
return `writeln("` ~ message ~ `");`;
}
void main() {
mixin (printStatement("hello world"));
mixin (printStatement("hi world"));
}
插件名字歧义:
import std.stdio;
template Templ() {
int i;
void print() {
writeln(i); //模板中的i
}
}
void main() {
int i;
mixin Templ;
i = 42; // 主中的i
writeln(i); // 主中
print(); // 模板中
}
多插件名冲突,解决:
mixin Templ A; // Defines A.i
mixin Templ B; // Defines B.i
//再定义一个名字.
A.i = 42;
串插件没有名字空间.
void main() {
mixin ("int i;");
mixin ("int i;"); // 编译错误
i = 42;
}
一种简单消歧方法,把串插件
搞成模板插件
,然后消歧:
template Templatize(string str) {
mixin (str);
}
void main() {
mixin Templatize!("int i;") A;//靠的是这两句
mixin Templatize!("int i;") B;//靠的是这两句
A.i = 42;//消歧
}
串插件
在操作符重载时,很有用.操作符重载定义为模板也是为了方便生成代码.
串插件
用在析构器中:
import std.stdio;
mixin template Foo() {
~this() {
writeln("Destructor mixed-in by Foo");
}
}
mixin template Bar() {
~this() {
writeln("Destructor mixed-in by Bar");
}
}
struct S {
~this() {
writeln("Actual destructor");
}
mixin Foo;
mixin Bar;
}
void main() {
auto s = S();
}
析构顺序与插件调用顺序相反.
这种方式允许插入不同的资源至一个类型,资源自己在不同插件模板元中清理自己.然后使用者调用相应析构插件.
由于写本书时的漏洞,析构器目前不能这样.但当前(2020)不确定.
此外,串插件的析构器确实与类型析构器冲突了.
int[] filter(string predicate)(in int[] numbers) {
int[] result;
foreach (number; numbers) {
if (mixin (predicate)) {
result ~= number;
}
}
return result;
}
上面的可以用λ
来写,更方便.在没有λ
时很流行.
这样使用:
int[] numbers = [ 1, 8, 6, -2, 10 ];
int[] chosen = filter!"number < 7"(numbers);
是不是,太暴力了.且名字必须匹配.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现