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

Reply via email to