Generic Property Implementation
Simen Kjærås
simen.kjaras at gmail.com
Mon Mar 12 09:54:20 UTC 2018
On Monday, 12 March 2018 at 08:59:49 UTC, Alex wrote:
> An incomplete type is perfectly ok, so there should be no
> problem with a pointer of the same type inside a struct.
> If accidentally the pointer refers "this", then it must have
> been set after construction. As before construction the value
> of "this"-pointer does not exist and after the construction the
> pointer to "this" has the default value of null.
>
> Therefore, you are aware of this circumstance and appropriate
> movings of the pointer value are also up to you.
But I don't have a hook to update the pointer when the struct is
moved. The GC may move my struct without informing me in any way.
In fact, even just a copy construction will break this:
struct S {
S* ptr;
this(int dummy) {
ptr = &this;
}
~this() {
// This assert will fail.
assert(ptr == &this);
}
}
unittest {
S s1 = S(0);
S s2 = S(0);
assert(&s1 == s1.ptr);
assert(&s2 == s2.ptr);
s1 = s2;
}
The reason is copy construction makes a copy[1] of the lhs, then
performs the copy construction[2]. If the copy construction[2]
succeeds, the copy[1] is destroyed. If not, the copy[1] is
blitted back over the original, to give the impression that
nothing ever happened.
When the destructor is called on the copy[1], &this returns a
different address from what it did before, since it's a copy and
logically resides at a different address.
> struct SomeType(alias fn) {}
>
> is (or has to be) lowered to something like
>
> struct SomeType
> {
> typeof(fn)* fn;
> }
>
> Even if fn contains a frame pointer to S it is perfectly legal
> to have such a type. SomeType would contain a delegate then.
Indeed. But stack frames aren't copied or moved the way structs
are.
> However, I think, the syntax
>
>>> struct S {
>>> int n, m;
>>> SomeType!(() => n + m) a;
>>> }
>
> is still invalid and
>
>>> struct S {
>>> int n, m;
>>> auto a() { return SomeType!(() => n + m)(); }
>>> }
>
> has another semantics.
>
> The latter closures above the current values inside of S.
> The former has to be constructible without the context, as it
> is perfectly legal to write
>
> struct Outer
> {
> struct Inner{}
> }
>
> void main()
> {
> auto i = Outer.Inner();
> }
>
> but would be impossible with this syntax.
I'm not using any inner structs in my examples. SomeType is
assumed to be a separate type that knows nothing about S. If
you're saying this should work:
unittest {
auto tmp = typeof(S.a)();
}
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(); }
}
unittest {
// cannot access frame pointer of foo.S.a.SomeType!(delegate
() => this.n).SomeType
auto tmp = typeof(S.a())();
}
--
Simen
More information about the Digitalmars-d-learn
mailing list