32用d编程模板
模板可编写通用算法/数据结构
d模板
非常强大.函数,结构,类
模板.
import std.stdio;
void printInParens(T)(T value) {
writefln("(%s)", value);
}
void main() {
printInParens(42); // with int
printInParens(1.2); // with double
auto myValue = MyStruct();
printInParens(myValue); // with MyStruct
}
struct MyStruct {
string toString() const {
return "hello";
}
}
//返回不等切片,删除具某个值的切片
T[] removed(T)(const(T)[] slice, T value) {
T[] result;
foreach (element; slice) {
if (element != value){
result ~= element;
}
}
return result;
}
特化示例:
T getResponse(T)(string question) {
writef("%s (%s): ", question, T.stringof);
T response;
readf(" %s", &response);
return response;
}
T getResponse(T : Point)(string question) {//点
writefln("%s (Point)", question);
auto x = getResponse!int(" x");
auto y = getResponse!int(" y");
return Point(x, y);
}
再加:
import std.math;
// ...
struct Point {
int x;
int y;
int distanceTo(in Point that) const {
immutable real xDistance = x - that.x;
immutable real yDistance = y - that.y;
immutable distance = sqrt((xDistance * xDistance) +
(yDistance * yDistance));
return cast(int)distance;
}
}
进一步:
struct Point(T) {//点为模板了
T x;
T y;
T distanceTo(in Point that) const {
immutable real xDistance = x - that.x;
immutable real yDistance = y - that.y;
immutable distance = sqrt((xDistance * xDistance) +
(yDistance * yDistance));
return cast(T)distance;
}
}
结构与类必须提供模板参数
:
auto center = Point!int(0, 0);
auto branch = Point!int(100, 100);
writeln("Distance: ", center.distanceTo(branch));
//可以这样了.
auto point1 = Point!double(1.2, 3.4);
auto point2 = Point!double(5.6, 7.8);
writeln(point1.distanceTo(point2));
但这时不能编译:
T getResponse(T : Point)(string question) {
writefln("%s (Point)", question);
auto x = getResponse!int(" x");
auto y = getResponse!int(" y");
return Point(x, y);
}
要变成这样:
Point!T getResponse(T : Point!T)(string question) { // 2, 1
writefln("%s (Point!%s)", question, T.stringof); // 5,现在打印串名.
auto x = getResponse!T(" x");//3a
auto y = getResponse!T(" y");//3b
return Point!T(x, y);//4
}
默认模板参数,int
又回来了.
T getResponse(T = int)(string question) {
// ...
}
// ...
auto age = getResponse("哈哈");
在类/结构
中省略不了了.
struct Point(T = int) {
// ...
}
// ...
Point!() center;//这也是用!的一个原因.
也可以限制多个:
void myTemplate(T0, T1 = int, T2 = char)() {
// ...
}
不同模板参数的类型是不同的类型.不能互换.
类模板示例:栈(简单):
class Stack(T) {
private:
T[] elements;
public:
void push(T element) {
elements ~= element;
}//这两个是一般成员函数
void pop() {
--elements.length;
}
T top() const @property {
return elements[$ - 1];
}//这两个作为属性.提供简单栈信息
size_t length() const @property {
return elements.length;
}
}
单元测试如下:
unittest {
auto stack = new Stack!int;
//新加元素必在上面
stack.push(42);
assert(stack.top == 42);
assert(stack.length == 1);
// .top 和 .length 不影响元素
assert(stack.top == 42);
assert(stack.length == 1);
//必在上
stack.push(100);
assert(stack.top == 100);
assert(stack.length == 2);
//移除后进的元素,冒出先进的元素
stack.pop();
assert(stack.top == 42);
assert(stack.length == 1);
//移完了,就是空
stack.pop();
assert(stack.length == 0);
}
下面添加用户定义类型:
struct Point(T) {
T x;T y;
string toString() const {
return format("(%s,%s)", x, y);
}
}
定义为:
auto points = new Stack!(Point!double);
中文名为:双精的点的栈
,双精!点!栈
import std.string;
import std.stdio;
import std.random;
struct Point(T) {
T x;
T y;
string toString() const {
return format("(%s,%s)", x, y);
}
}
//返回随机
double random_double()
out (result) {
assert((result >= -0.50) && (result < 0.50));
} do {
return (double(uniform(0, 100)) - 50) / 100;
}
// 返回随机个Point!double元素.
Stack!(Point!double) randomPoints(size_t count)
out (result) {
assert(result.length == count);
} do {
auto points = new Stack!(Point!double);
foreach (i; 0 .. count) {
immutable point = Point!double(random_double(),
random_double());
writeln("adding : ", point);
points.push(point);
}
return points;
}
void main() {
auto stackedPoints = randomPoints(10);
while (stackedPoints.length) {
writeln("removing: ", stackedPoints.top);
stackedPoints.pop();
}
}
体
已弃用.用do
.
函数模板二分搜索示例:
/* 有,返回索引.无返回最大*/
size_t binarySearch(const int[] values, in int value) {
if (values.length == 0) {//空
return size_t.max;
}
immutable midPoint = values.length / 2;
if (value == values[midPoint]) {
// Found.
return midPoint;
} else if (value < values[midPoint]) {
return binarySearch(values[0 .. midPoint], value);
//搜索小半
} else {//搜索大半
auto index =binarySearch(values[midPoint + 1 .. $], value);//从中间值+1开始的
if (index != size_t.max) {
//找到索引,加个1
index += midPoint + 1;
}
return index;
}
assert(false, "不可达");
}
以上是简单版,测试后,将整
改成T
:
size_t binarySearch(T)(const T[] values, in T value) {
// ...
}
没有==
与<
比较操作.因而重新加上:
struct Point(T) {
// ...
int opCmp(const ref Point that) const {
return (x == that.x
? y - that.y
: x - that.x);
}//加上自定义
}
模板根据参数
+模板,生成实例.
模板是编译时
特征.指定模板参数可以定义
function,struct,和class
类模板
void functionTemplate(T)(T functionParameter) {
// ...
}
class ClassTemplate(T) {
// ...
}
auto object1 = new ClassTemplate!(double);
auto object2 = new ClassTemplate!double;
不同类型模板实例是不同的类型:
assert(typeid(ClassTemplate!int) !=
typeid(ClassTemplate!uint));
只能给函数推导模板.不能给(类/构)模板推导.
类特化与默认参数=
:
class ClassTemplate(T : dchar) {
// ...
}
void functionTemplate(T = long)(T functionParameter) {
// ...
}
【推荐】国内首个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岁的心里话
· 按钮权限的设计及实现