C++ vs D: Default param values and struct to array casting

Ali Çehreli acehreli at yahoo.com
Fri Sep 6 18:31:29 UTC 2019


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



More information about the Digitalmars-d-learn mailing list