d的自动构造器模板

原文
通用,hashOf函数:

override size_t toHash() const {
    return hashOf(y, hashOf(x));
}

这里:

enum defaultClassConstructor = q{
  this(typeof(this.tupleof) params) {
    static foreach (i; 0..this.tupleof.length)
      this.tupleof[i] = params[i];
  }
};

struct Color {
  ubyte r, g, b, a;
}

class Point {
  Color c;
  int x, y;
  bool h;

  mixin(defaultClassConstructor);
}

unittest
{
  Color foo = { r : 0x30,
                g : 0xd5,
                b : 0xc8
  };

  auto bar = new Point(foo, 320, 240, true);

  assert(bar.h);
  assert(bar.x == 320);
  assert(bar.y == 240);
  assert(bar.c.a == 0);
  assert(bar.c.r == 48);
  assert(bar.c.g == 213);
  assert(bar.c.b == 200);
}
//另一版本
void main()
{
  auto colorWithAlpha = vec4i(100, 150, 200, 300);
       colorWithAlpha.r = 120;
  assert(colorWithAlpha.r == 120);
  assert(colorWithAlpha.g == 150);
  assert(colorWithAlpha.b == 200);
  assert(colorWithAlpha.a == 300);

  auto point3D = vec3i(100, 200, 300);
       point3D.z /= 2;
  assert(point3D.x == 100);
  assert(point3D.y == 200);
  assert(point3D.z == 150);

  auto point2D = vec2i(100, 200);
       point2D.y = point3D.z;
  assert(point2D.x == 100);
  assert(point2D.y == 150);
}

template vec2(T) { alias Vector!(T, 2) vec2; }
alias vec2!int    vec2i;
alias vec2!float  vec2f;
alias vec2!double vec2d;

template vec3(T) { alias Vector!(T, 3) vec3; }
alias vec3!int    vec3i;
alias vec3!float  vec3f;
alias vec3!double vec3d;

template vec4(T) { alias Vector!(T, 4) vec4; }
alias vec4!int    vec4i;
alias vec4!float  vec4f;
alias vec4!double vec4d;

enum isVector(T) = is(T : Vector!A, A...);

struct Vector(T, int N)
{
  static assert(N >= 1);
  import std.conv,
         std.format,
         std.traits;

  union
  {
    T[N] v;
    struct
    {
      static if(N >= 1)
      {
        T x; alias x r;
      }
      static if(N >= 2)
      {
        T y; alias y g;
      }
      static if(N >= 3)
      {
        T z; alias z b;
      }
      static if(N >= 4)
      {
        T w; alias w a;
      }
    }
  }

  this(Args...)(Args args)
  {
    static if (args.length == 1)
    {// 从简单值构造向量
      opAssign!(Args[0])(args[0]);
    }
    else
    { // 验证总参个数
      template argCount(T...)
      {
        static if(T.length == 0)
          enum argCount = 0; // 递归完成
        else static if(isVector!(T[0]))
          enum argCount = T[0]._N + argCount!(T[1..$]);
        else
          enum argCount = 1 + argCount!(T[1..$]);
        }

        static assert(argCount!Args <= N, "Too many arguments in vector constructor");

        int index = 0;
        foreach(arg; args)
        {
          static if(isAssignable!(T, typeof(arg)))
          {
            v[index] = arg;
            index++; // 
          }
          else static if (isVector!(typeof(arg)) && isAssignable!(T, arg._T))
          {
            mixin(generateLoopCode!("v[index + @] = arg[@];", arg._N)());
            index += arg._N;
          }
          else static assert(false, "Unrecognized argument in Vector constructor");
        }
        assert(index == N, "Bad arguments in Vector constructor");
      }
  }

  /// 用静态数组赋值
  ref Vector opAssign(U)(U arr)
  if ((isStaticArray!(U) && isAssignable!(T, typeof(arr[0])) && (arr.length == N)))
  {
    mixin(generateLoopCode!("v[@] = arr[@];", N)());
    return this;
  }

  /// 用动态数组
  ref Vector opAssign(U)(U arr)
  if (isDynamicArray!(U) && isAssignable!(T, typeof(arr[0])))
  {
    assert(arr.length == N);
    mixin(generateLoopCode!("v[@] = arr[@];", N)());
    return this;
  }

  /// 相同向量
  ref Vector opAssign(U)(U u)
  if (is(U : Vector))
  {
    v[] = u.v[];
    return this;
  }

  /// 其余向量类型
  ref Vector opAssign(U)(U x)
  if(isVector!U && isAssignable!(T, U._T)
                && (!is(U: Vector))
                && (U._N == _N)
     ) {
    mixin(generateLoopCode!("v[@] = x.v[@];", N)());
    return this;
  }

  /// 内容指针
  inout(T)* ptr() inout @property
  {
    return v.ptr;
  }

  /// 良好打印
  string toString() const nothrow
  {
    try
      return format("%s", v);
    catch (Exception e)
      assert(false); // 不应该
  }

  private
  {
    enum _N = N;
    alias T _T;

    // 可转换类型
    template isConvertible(T)
    {
      enum bool isConvertible =
         (!is(T : Vector)) &&
           is(typeof( { T x_Detect;
                        Vector v = x_Detect;
                      }()
                    )
             );
    }

    static
    string generateLoopCode(string str, int N)()
    {
      import std.string;
      string result;
      for(int i; i < N; ++i)
      {
        string index = ctIntToString(i);
        // replace all @ by indices
        result ~= str.replace("@", index);
      }
      return result;
    }

    // 加速ctfe.
    static string ctIntToString(int n)
    {
      static
      immutable string[16] table = ["0", "1", "2",
                                    "3", "4", "5",
                                    "6", "7", "8",
                                    "9"];
      if (n < 10) return table[n];
      else return n.to!string;
    }
  } // 私
}
posted @   zjh6  阅读(9)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示