22用d编程重载运算符

对类,不能重载opAssign,因为是按引用的.赋值是引用.
重载运算符,主要是为了方便书写.

struct TimeOfDay {
// ...
    ref TimeOfDay opOpAssign(string op)(in Duration duration)//(1)
            if (op == "+") {                                 //(2)
        minute += duration.minute;
        hour += minute / 60;
        minute %= 60;hour %= 24;
        return this;//本为引用?
    }
}

opOpAssign(string op),表示是赋值大类下面的重载
opOpAssign!"+"就是+=符的重载,注意,返回的是引用.
c++不一样,c++是指针.而d引用.
要注意,重载的函数的语义最好是直观的,不要瞎搞.
可重载的操作符有:
一元操作符:

操作符意思
-对象取反“-”
+对象与+一样“+”
~对象按位取反“~”
*对象访问指针“*”
++对象加1“++”
--对象减1“–”

不能自定义后++与后--,编译器给你搞
二元操作符:
+ - * / % ^^ & ^ << >> >>> ~ in == != < <= > >= = += -= *= /= %= ^^= &= ^= <<= >>= >>>= ~=
有两种:
x 操作 y,

x.opBinary!"op"(y);
y.opBinaryRight!"op"(x);
函数名示例
opIndex集合[i]
opIndexAssign集合[i] = 7
opIndexUnary++集合[i]
opIndexOpAssign集合[i] *= 2
opDollar集合[$ - 1]
opSlice集合[]
opSlice(正,正)集合[i…j]

还有opCall((...)),opCast(转!...),opDispatch(未知函数)

struct Duration {
    int minute;

    ref Duration opUnary(string op)()
            if ((op == "++") || (op == "--")) {
        mixin (op ~ "minute;");
        return this;
    }

    ref Duration opOpAssign(string op)(in int amount)
            if ((op == "+") || (op == "-")) {
      //(op == "*") || (op == "/")) {//扩展
        mixin ("minute " ~ op ~ "= amount;");
        return this;
    }
    ref Duration opOpAssign(string op)(in int amount)
//不要限制了.
        mixin ("minute " ~ op ~ "= amount;");
        return this;
    }
}
  int i = 1;
    writeln(":", &i);
    writeln(":", &(++i));
//看看地址

修改自身的有opUnary!"++", opUnary!"--"所有opOpAssign重载.
opEquals,必须返回
in一般返回对象,也可返回.
表示<, <=, >, 和 >=opCmp返回
创建新对象的操作符:一元-, +, ~;二元~.及
算术操作:+, -, 星, /, %, 和 ^^,
按位操作&, |, ^, <<, >>, 和 >>>opAssign,有时op赋值会返回常 引用(钥匙).而不是实体.
opDollar返回容器元素个数
未限制操作符:
一元 星, opCall, opCast, opDispatch, opSlice, 和所有opIndex
opEquals 和 opCmp必须一致,如果相等,则比较必须为0.一般可以不定义相等操作,编译器自动生成.
有些需要不同的相等定义,可以定义一个.
opCmp用于排序.可以控制<,<=,>,>=,返回类型为.
如左在右前,则返回负,左在右后,返回正.相等为0.

 int opCmp(in TimeOfDay rhs) const {
        return (hour == rhs.hour
                ? minute - rhs.minute
                : hour - rhs.hour);
    }//注意,减号可能导致溢出.
struct S {
    int i;

    int opCmp(in S rhs) const {
        return i - rhs.i;          // 漏洞
    }//-2比`最大整更大`?.
}

void main() {
    assert(S(-2) > S(int.max));    // 错误排序
}
//算法改进
import std.algorithm;

struct S {
    string name;
    int opCmp(in S rhs) const {
        return cmp(name, rhs.name);//字母序比较
    }
}

opCall()用于调用函数.
static opCall(),用来静态创建默认()
定义opCall()禁止了编译器自动生成的构造函数
因此这样用:

struct LinearEquation {
    double a;
    double b;

    double opCall(double x) const {
        return a * x + b;
    }
}
//这样用
   LinearEquation equation = { 1.2, 3.4 };
    double y = equation(5.6);//像函数一样使用

下面是个双端队列

import std.stdio;
import std.string;
import std.conv;

struct DoubleEndedQueue //也叫双列
{
private:

    int[] head;    //头列
    int[] tail;    //尾列

    ref inout(int) elementAt(size_t index) inout {
        return (index < head.length
                ? head[$ - 1 - index]
                : tail[index - head.length]);
    }//实际切片

public:

    string toString() const {
        string result;

        foreach_reverse (element; head) {
            result ~= format("%s ", to!string(element));
        }

        foreach (element; tail) {
            result ~= format("%s ", to!string(element));
        }

        return result;
    }

    version (none) {//tostring的简单有效实现
    void toString(void delegate(const(char)[]) sink) const {
        import std.format;
        import std.range;

        formattedWrite(//格式写
            sink, "%(%s %)", chain(head.retro, tail));
    }}

    void insertAtHead(int value) {
        head ~= value;
    }//加元素,加至头

    ref DoubleEndedQueue opOpAssign(string op)(int value)
            if (op == "~") {
        tail ~= value;
        return this;
    }//加至尾

    inout(int) opIndex(size_t index) inout {
        return elementAt(index);
    }//[]操作

    int opIndexUnary(string op)(size_t index) {
        mixin ("return " ~ op ~ "elementAt(index);");
    }//一元式

    int opIndexAssign(int value, size_t index) {
        return elementAt(index) = value;
    }
    int opIndexOpAssign(string op)(int value, size_t index) {
        mixin ("return elementAt(index) " ~ op ~ "= value;");
    }//[i]+=右

    size_t opDollar() const {
        return head.length + tail.length;
    }
}

void main() {
    auto deque = DoubleEndedQueue();

    foreach (i; 0 .. 10) {
        if (i % 2) {
            deque.insertAtHead(i);

        } else {
            deque ~= i;
        }
    }
    writefln("[3]元素: %s",deque[3]);//访问元素
    ++deque[4];            // 加元素
    deque[5] = 55;         // 给元素赋值
    deque[6] += 66;        // 加至元素

    (deque ~= 100) ~= 200;

    writeln(deque);
}

(deque ~= 100) ~= 200;因为,~=为引用类型.

    deque[] *= 10;    //每个元素*

    // 等价于
    {
        auto range = deque.opSlice();
        range.opOpAssign!"*"(10);//区间切片再*
    }

再如:

import std.exception;

struct DoubleEndedQueue {
// ...
    inout(Range) opSlice() inout {//返回区间
        return inout(Range)(head[], tail[]);
    }

    inout(Range) opSlice(size_t begin, size_t end) inout {//区间[头..尾]
        enforce(end <= opDollar());
        enforce(begin <= end);
        if (begin < head.length) {
            if (end < head.length) {//区间全在头内
                return inout(Range)(head[$ - end .. $ - begin],[]);
            } else {//部分在头,部分在尾
                return inout(Range)(head[0 .. $ - begin],tail[0 .. end - head.length]);
            }
        } else {//完全在尾
            return inout(Range)([],tail[begin - head.length .. end - head.length]);
        }
    }

    struct Range {//区间细节
        int[] headRange,tailRange;
        Range opUnary(string op)() {//一元操作
            mixin (op ~ "headRange[];");
            mixin (op ~ "tailRange[];");
            return this;
        }

        Range opAssign(int value) {//赋值
            headRange[] = value;
            tailRange[] = value;return this;
        }

        Range opOpAssign(string op)(int value) {
            mixin ("headRange[] " ~ op ~ "= value;");
            mixin ("tailRange[] " ~ op ~ "= value;");
            return this;
        }//赋值操作
    }
}

void main() {
    auto deque = DoubleEndedQueue();
    foreach (i; 0 .. 10) {
        if (i % 2) deque.insertAtHead(i);
        else {deque ~= i;}
    }

    writeln(deque);deque[] *= 10;
    deque[3 .. 7] = -1;writeln(deque);
}

opCast转换类型,是个模板.
opDispatch,最后的调用.包揽所有.

import std.stdio;
import std.conv;

struct Duration {
    int hour;
    int minute;

    double opCast(T : double)() const {
        return hour + (to!double(minute) / 60);
    }//可按这种方式转成`双精`
    bool opCast(T : bool)() const {
        return (hour != 0) || (minute != 0);
    }//逻辑表达式中,可以自动调用这个转换.
}//而其他转换,得显式调用.

void main() {
    auto duration = Duration(2, 30);
    double d = to!double(duration);
    writeln(d);
}
void foo(bool b) {
    // ...
}
    foo(duration);//不行,编译不过
    bool b = duration;//不行,编译不过

暴力指派函数,最后的函数.

import std.stdio;

struct Foo {
    void opDispatch(string name, T)(T parameter) {
        writefln("Foo.opDispatch - name: %s, value: %s",name, parameter);
    }
}

void main() {
    Foo foo;
    foo.aNonExistentFunction(42);
    foo.anotherNonExistentFunction(100);
}

还有二元的:opBinaryRight!“in”

 if (time in lunchBreak) {
//等价于
if (lunchBreak.opBinaryRight!"in"(time)) {
//应该叫in的右二元操作
//-----
import std.stdio;
import std.string;
struct Duration {int minute;}

struct TimeOfDay {
    int hour;int minute;

    ref TimeOfDay opOpAssign(string op)(in Duration duration)
            if (op == "+") {
        minute += duration.minute;
        hour += minute / 60;
        minute %= 60;hour %= 24;
        return this;
    }

    int opCmp(in TimeOfDay rhs) const {
        return (hour == rhs.hour
                ? minute - rhs.minute
                : hour - rhs.hour);
    }

    string toString() const {
        return format("%02s:%02s", hour, minute);
    }
}

struct TimeSpan {
    TimeOfDay begin;
    TimeOfDay end;    // 尾端

    bool opBinaryRight(string op)(TimeOfDay time) const
            if (op == "in") {
        return (time >= begin) && (time < end);
    }
}

void main() {
    auto lunchBreak = TimeSpan(TimeOfDay(12, 00),
                               TimeOfDay(13, 00));

    for (auto time = TimeOfDay(11, 30);
         time < TimeOfDay(13, 30);
         time += Duration(15)) {

        if (time in lunchBreak) {
            writeln(time, " 吃饭时间");

        } else {
            writeln(time, " 工作时间");
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值