D言語における共用体とVariant

共用体と演算子の多重定義を使って、論理値、整数、実数、複素数、文字列、ポインタを代入できる構造体 Any を作成してみました。でも、実際に使うなら、配列も扱える Variant のほうが便利かも...

any.d
enum Type {VOID, BOOL, LONG, REAL, CREAL, STRING, POINTER}

struct Any {
  Type type = Type.VOID;

  union {
    bool b;
    long l;
    real r;
    creal c;
    string s;
    void* p;
  }

  void opAssign(bool b) {
    type = Type.BOOL;
    this.b = b;
  }

  void opAssign(long l) {
    type = Type.LONG;
    this.l = l;
  }

  void opAssign(real r) {
    type = Type.REAL;
    this.r = r;
  }

  void opAssign(creal c) {
    type = Type.CREAL;
    this.c = c;
  }

  void opAssign(string s) {
    type = Type.STRING;
    this.s = s;
  }

  void opAssign(void* p) {
    type = Type.POINTER;
    this.p = p;
  }
}

void main() {
  Any any;
  any = true;
  any = 10;
  any = 0.1;
  any = 1+2i;
  any = "Hello!";
  any = (int i, int j) => i + j;
}

variant.d
import std.variant;

void main() {
  Variant variant;
  variant = true;
  variant = 10;
  variant = 0.1;
  variant = 1+2i;
  variant = "Hello!";
  variant = (int i, int j) => i + j;
  variant = new int[100];
}
広告

D言語によるテンプレートプログラミング

D言語ではテンプレート引数に、(bool、int、real、char、string 等)、(数値と文字列)、記号(モジュール名、クラス名、関数名、関数リテラル等)を用いることができます。記号をテンプレート引数にする場合は、alias を使って宣言します。

template.d
import std.stdio;

template Tmplt(T, int I) {
  T t;
  struct Strct {
    T t;
  }
  T foo(T t) {
    return I + t;
  }
}

class Clss(T, int I) {
  T t;
  T foo(T t) {
    return I + t;
  }
}

T fnctn(T, int I)(T t) {
  return I + t;
}

int apply(alias A)(int i, int j) {
  return A(i, j);
}

int add(int i, int j) {
  return i + j;
}

void main() {
  Tmplt!(int, 0).t = 0;
  Tmplt!(int, 0).Strct strct = {0};
  writeln(Tmplt!(int, 0).foo(1));
  auto clss = new Clss!(int, 0);
  writeln(clss.foo(1));
  writeln(fnctn!(int, 1)(1));
  writeln(apply!(add)(1, 1));
  writeln(apply!((int i, int j) => i + j)(1, 1));
}