On 09/06/2019 02:14 AM, Andrew Edwards wrote:

> I'm seeking some pointers on how to define these in D

Here is my attempt:

struct Demo {
// NOTE: The types and number of elements can be templatized and mixed-in like
  // mixin (makeMembers!T(N));

  float a = 0;
  float b = 0;
  float c = 0;
  float d = 0;

  // Then these checks would be unnecessary
  static assert(a.sizeof == b.sizeof);
  static assert(b.sizeof == c.sizeof);
  static assert(c.sizeof == d.sizeof);

  // And this would be equal to N
  enum length = this.sizeof / a.sizeof;

  this(const(float)[] init...) {
    asSlice[0..init.length] = init;
  }

  auto asSlice() inout {
    // WARNING: As UNDEFINED BEHAVIOR as in the C++ code!
    return (&a)[0..length];
  }

  ref asArray(size_t n = length)() inout {
    // WARNING: As UNDEFINED BEHAVIOR as in the C++ code!
    return *cast(float[n]*)(&a);
  }

  ref inout(float) opIndex(size_t i) inout {  // [3] [4]
    return asSlice[i];
  }
}

unittest {
  import std.algorithm;

  static assert (Demo.length == 4);

  void enforceMemberWiseEquality(Demo d, const(float)[] values) {
    switch (values.length) {
    case 4:
      assert(d.d == values[3]);
      goto case;

    case 3:
      assert(d.c == values[2]);
      goto case;

    case 2:
      assert(d.b == values[1]);
      goto case;

    case 1:
      assert(d.a == values[0]);
      goto default;

    default:
      break;
    }
  }

  const init = [1.0f, 2.0f, 3.0f, 4.0f];

  // Test constructing with different number of expressions
  foreach (length; 0..init.length) {
    auto testInit = init[0..length];
    const d = Demo(testInit);
    enforceMemberWiseEquality(d, testInit);
    assert(d.asArray[0..length].equal(testInit));
    assert(d.asSlice[0..length].equal(testInit));}
}

extern (C++) void fun(float* col) {
  // do fun stuff
}

extern (C++) void moreFun(ref const(Demo) d) { // [1]
  // you guessed it... more fun stuff
}

// This is needed because operations inside asSlice are not allowed
// at compile time. (That's why I could not make this variable 'static'.
immutable(Demo) moreFun_default;
shared static this() {
  moreFun_default = Demo(0.1f, 0.3f, 7.5f, 1.5f);
}

extern (C++) void moreFun() { // [1]
  // We need this function because D does not allow rvalue references.
  // Here, we're passing an lvalue.
  moreFun(moreFun_default);
}

int main()
{
  Demo inst = Demo(0.1f, 0.3f, 7.5f, 1.5f);
  fun(inst.asSlice.ptr); // [2]
  moreFun();
  return 0;
}

Ali

Reply via email to