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) {
    // ...
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值