Generic Property Implementation

Alex sascha.orlov at gmail.com
Mon Mar 12 14:04:20 UTC 2018


On Monday, 12 March 2018 at 13:04:54 UTC, Simen Kjærås wrote:
> On Monday, 12 March 2018 at 10:37:00 UTC, Alex wrote:
>> Sure, you have.
>> https://dlang.org/spec/struct.html#assign-overload
>> Point #4.
>> In this case,
>>
>> ref S opAssign(ref S rhs)
>> {
>>     return this;
>> }
>
> True. Can you fix these, too?
>
> struct S {
>     S* ptr;
>     this(int dummy) {
>         ptr = &this;
>     }
>     ~this() {
>         assert(ptr == &this);
>     }
> }
>
> void test(S s) {}
>
> unittest {
>     test(S(0));
> }
>
> S test2() {
>     return S(0);
> }
>
> unittest {
>     S s = test2();
> }
>

ok... this is a little bit more tricky, as there is no assignment 
now. :)
But in this two cases I assume, you want to have explicit pass by 
reference, no?

struct S {

     S* ptr;
     this(int dummy) {
         ptr = &this;
     }
	
     ~this() {
         assert(ptr == &this);
     }
}

void test(ref S s){}

unittest {
     auto s = S(0);
     test(s);
     /*
     if I call test(S(0)) with void test(S s) as in your example,
     neither the postblit nor opAssign is called... hm... no idea 
why...
     */
}

auto test2() {
     return new S(0);
}

unittest {
     auto s = test2();
     /*
     This example differs more from the post before :) test2 is a 
true factory now,
     it has to grant the right setting of all members...
     */
}

>> Another point is, that I hope, that pointers don't move 
>> anywhere, as in C, by definition.
>
> And why not? D allows for moving garbage collectors.

If it were allowed, then "contiguous memory allocation" for 
arrays would be senseless.

>
>>> unittest {
>>>     auto tmp = typeof(S.a)();
>>> }
>>
>> I thought, this shouldn't be possible (at least in my mind)
>>
>>> It wouldn't, and such code is not possible in D today:
>>>
>>> struct S {
>>>     int n;
>>>     auto a() { return SomeType!(() => n)(); }
>>> }
>>>
>>> struct SomeType(alias fn) {
>>>     int get() { return fn(); }
>>> }
>>>
>> But this is clearly valid.
>
> Yes, it's an example of code that works in D today, with 
> similar semantics to those implied in the other example. It's 
> meant to show that just like `auto tmp = typeof(S.a())()` 
> doesn't work today, it shouldn't work with the types used in my 
> other example.
>
>
>
>>> unittest {
>>>    // cannot access frame pointer of 
>>> foo.S.a.SomeType!(delegate () => this.n).SomeType
>>>    auto tmp = typeof(S.a())();
>>> }
>>>
>> For sure, tmp cannot be defined without an instance of S. So 
>> the correct unittest in my eyes would be:
>> unittest {
>>    S s;
>>    auto res = s.a;
>>    assert(res.get == S.init.n);
>> }
>
> I think we may be speaking past one another. Yes, your unittest 
> would be expected to pass.
>
> If we go back to the example code:
>
> struct S1 {
>     int n, m;
>     SomeType!(() => n + m) a;
> }
>
> vs.
>
> struct S2 {
>     int n, m;
>     auto a() { return SomeType!(() => n + m)(); }
> }
>
> I would expect typeof(S1.a) and typeof(S2.a()) to be 
> equivalent. I don't see a good reason why I should be able to 
> construct an instance of typeof(S1.a), since I can't construct 
> a typeof(S2.a()).
>
> I see your point that "The latter closures above the current 
> values inside of [S2]". I'm saying I want the former to do the 
> same. I understand that it currently doesn't, and I argue that 
> having it do the same would be a much more useful behavior. 
> Apart from the fact it's impossible, I don't see any good 
> reason not to make it work. :p

I see your point too :)
But the latter form just grants the existence of an instance of 
S, whereas the first form doesn't.
By the way, this would work:

struct S1 {
     static int n, m; // added a static here.
     SomeType!(() => n + m) a;
}

struct SomeType(alias fn){}

> --
>   Simen


More information about the Digitalmars-d-learn mailing list