Unexpected aliasing

Bastiaan Veelo Bastiaan at Veelo.net
Tue Nov 12 08:43:30 UTC 2019


On Monday, 11 November 2019 at 21:52:12 UTC, Jonathan M Davis 
wrote:
> On Monday, November 11, 2019 12:17:37 PM MST Bastiaan Veelo via 
> Digitalmars- d-learn wrote:

[...]

>> I could use some help in rewriting the code below so that arr1 
>> and arr2 each have their own data; ideally with minimal 
>> changes so that I can make the transcompiler do the right 
>> thing.
>>
>> Thanks!
>> Bastiaan.
>>
>> void main()
>> {
>>   import std.stdio;
>>
>>   WrapIntegerArray arr1;
>>   arr1[0] = 42;
>>
>>   WrapIntegerArray arr2;
>>
>>   writeln(arr2[0]); // 42, not 0.
>>   writeln("arr1.wrap.arr.ptr = ", arr1.wrap.arr.ptr);
>>   writeln("arr2.wrap.arr.ptr = ", arr2.wrap.arr.ptr); // 
>> identical
>>   assert(arr2[0] == 0); // fails
>> }
>>
>> struct IntegerArray
>> {
>>   int[] arr;
>>   alias arr this;
>>   this(int l)
>>   {
>>       arr = new int[l];
>>   }
>> }
>>
>> struct WrapIntegerArray
>> {
>>   auto wrap = IntegerArray(5); // This is CTFE! :-(
>>   alias wrap this;
>> }
>
> All struct and class members which are directly initialized 
> must have their values known at compile-time. For structs, 
> that's what goes in the init value for the type. A side effect 
> of this is that it's usually a bad idea to directly initialize 
> dynamic arrays which are member variables. You need to do the 
> initialization in a constructor. And for structs, if you need a 
> no-arg constructor, then you'll need to use a factory function 
> (since structs can't have no-arg constructors). e.g.
>
> struct WrapIntegerArray
> {
>     IntegerArray wrap;
>     alias wrap this;
>
>     this(int len)
>     {
>         wrap = IntegerArray(len);
>     }
> }
>
> or
>
> struct WrapIntegerArray
> {
>     IntegerArray wrap;
>     alias wrap this;
>
>     static make()
>     {
>         WrapIntegerArray retval;
>         retval.wrap = IntegerArray(5);
>         return retval;
>     }
> }
>
> So, you could then have something like
>
>     auto arr1 = WrapIntegerArray(5);
>     arr1[0] = 42;
>
>     or
>
>     auto arr1 = WrapIntegerArray.make();
>     arr1[0] = 42;
>
> but if you use the init value (which is what you get if you let 
> the type be default-initialized), then you'll have to first do 
> something to allocate the dynamic array if you want to be able 
> to index it, since if you don't give it a value at 
> compile-time, it's null (and you don't want to give it a value 
> at compile-time, because then every default-initialized struct 
> of that type will refer to the same dynamic array). Of course, 
> you could always just append values, and the dynamic array will 
> be allocated and grow accordingly, but that's obviously not the 
> same as allocating it up front to have a specific length.
>
> - Jonathan M Davis

Thank you Jonathan. A factory function seems to be what I need, 
then. It'll be an interesting challenge to have my transpiler 
detect when a factory function is needed, and making sure that 
they are called at the right places. But this might escalate 
since structs can have members that are structs that have a 
factory function. So the enclosing struct also needs a factory 
function. And so forth.

My problem is the translation of so called schematic arrays, a 
type that I have only seen in Extended Pascal. A schematic array 
is a type in which the length of the array is a parameter of the 
type. Extended Pascal does not have dynamic arrays, so schematic 
arrays are its attempt at improving a bit on just plain static 
arrays. The length parameter can be constant, in which it behaves 
akin to templates (which it doesn't have either), but it can also 
be set at run time during initialization (so I can't translate it 
to a template).

Maybe I can omit the translation of schematic arrays 
(IntegerArray in this case) altogether and instead detect where 
and how they are instantiated. Then replace them with a static 
array whenever the length is known at compile time, and a dynamic 
array otherwise. A static array is not nice, but at least they 
can be members of structs without a factory function. Either way, 
my transpiler needs to smarten up...

Bastiaan.


More information about the Digitalmars-d-learn mailing list