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

Jacob Carlborg doob at me.com
Sat Sep 7 13:19:54 UTC 2019


On 2019-09-06 11:14, Andrew Edwards wrote:
> C++ allows the for following:
> 
> struct Demo
> {
>      float a, b, c, d;
>      Demo() { a = b = c = d = 0.0f; }
>      Demo(float _a, float _b, float _c, float _d) {
>          a = _a;
>          b = _b;
>          c = _c;
>          d = _d;
>      }
>      float  operator[] (size_t i) const { return (&a)[i]; } //[3]
>      float& operator[] (size_t i) { return (&a)[i]; } //[4]
> }
> 
> void fun(float col[3])
> {
>      // do fun stuff
> }
> 
> void moreFun(const Demo& d = Demo(0.1f, 0.3f, 7.5f, 1.5f)) // [1]
> {
>      // you guessed it... more fun stuff
> }
> 
> int main(int argv, const char** argc)
> {
>      Demo inst = Demo(0.1f, 0.3f, 7.5f, 1.5f);
>      fun((float*)&inst); // [2]
>      moreFun();
>      return 0;
> }
> 
> I'm seeking some pointers on how to define these in D so that I can 
> instantiate them in D while still linking to the associated C++ library 
> or object file for the implementation. The main points of contention are 
> at [1] and [2] because I have no idea how to accomplish these.  I assume 
> that I can accomplish [3] and [4] with opIndex() and opIndexAssign(), 
> however I'm not understanding the slicing of the memory address at the 
> first member variable. I know that by indexing the memory address at the 
> member variable we are able treat the struct as an array but i do not 
> understand how to implement it in D.

In D you can use the built-in property `.tupleof` [1], available for 
structs and classes. That will give you a tuple, not an array. To get an 
array you can just wrap it in square brackets:

Demo inst = Demo(0.1f, 0.3f, 7.5f, 1.5f);
auto tuple = inst.tupleof; // "tuple" is a tuple
auto arr = [tuple];
static assert(is(typeof(arr) == float[]));

Converting the tuple to an array like that only works then all of the 
elements of the tuple has the same type.

Here's an example:

struct Test
{
     float a, b, c, d;

     float opIndex(size_t i)
     in(i >= 0 && i <= 3)
     {
         return [this.tupleof][i];
     }

     float get(size_t i)()
     {
         return this.tupleof[i];
     }
}

void main()
{
     auto t = Test(1, 2, 3, 4);
     assert(t[3] == 4);

     assert(t.get!3 == 4);
}

If you can provide the index at compile time you don't need to create an 
array of the the tuple. The "get" method shows that technique. 
Unfortunately "opIndex" cannot take the index as a template parameter. 
Here's the runnable version [2].

[1] https://dlang.org/spec/struct.html#struct_instance_properties
[2] https://run.dlang.io/is/7QYljZ

-- 
/Jacob Carlborg


More information about the Digitalmars-d-learn mailing list