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