d有趣的一元重载

原文

import std.stdio;

struct S
{
  int value;

  alias opCall this;
  this(int i) {
    value = i;
  }

  alias opAssign = opCall;
  @property opCall(int x) {
    return value = x;
  }

  @property opCall() inout {
    return value;
  }

  @property opOpAssign(string op)(int x) {
    write(":"); // 在此前
    mixin("return value"~op~"=x;");
  }
  // 不必: opUnary(string op)();
}

void main()
{

  S a = S(10),
    b = S(-1);

  writeln(a + b); // 9
  writeln(++a + b); // :10

  a += 10; // :

  assert(a == 21);
  writeln("\n--");

  writeln(-b); // 1
}

是的,有趣,我加了些注解:

import std.stdio;

struct S
{
    int value;

说明允许此类型对象隐式转换为'int'('opCall'返回类型).
即,由于opCall返回'int',现在知道S对象可隐式代替int.调用opCall来确定.

opCall允许像函数一样对待对象.如,当有"obj"时,可'obj()'.
注意:这让我有点困惑,因为下面有两个opCall定义,它们都返回"int".但是,因为下面这句,编译器选择无参别名本,所以没有歧义.

    alias opCall this;
    this(int i) {
        value = i;
    }

你正在为opCall指定(opAssign)新名.编译器是否考虑opCall来赋值,或它在找正确的opAssign定义:

    alias opAssign = opCall;

这是带'int'函数调用符,支持obj(42)等用法.

    @property opCall(int x) {
        return value = x;
    }

这是空参调用opCall,支持obj()用法.

    @property opCall() inout {
        return value;
    }

这是'obj+=42'等用法的操作符重载.

    @property opOpAssign(string op)(int x) {
        write(":"); 
        mixin("return value"~op~"=x;");
    }
    // 不需要: opUnary(string op)();
}

void main()
{
    /*这是普通构造对象*/
    S a = S(10),//有个逗号
    b = S(-1);

由于S未定义"+"操作,编译器会查找隐式转换,恰好是"int".以下表达式是两个整数的加法:10+(-1)

    writeln(a + b); // 9

尽管S不支持++运算符,但D编译器会找到+=操作并用a+=1替换++.然后隐式转换a'int',得到11.同样,表达式是11+(-1)整数加法.

    writeln(++a + b); // :10

    /* 用opOpAssign. */
    a += 10; // :

    /* 结果有意义. */
    assert(a == 21);
    writeln("\n--");
    writeln(-b); // 1
}
posted @   zjh6  阅读(17)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示