difficulties with const structs and alias this / template functions
Stanislav Blinov
stanislav.blinov at gmail.com
Mon Nov 19 13:34:50 UTC 2018
On Monday, 19 November 2018 at 12:28:43 UTC, Dennis wrote:
> On Monday, 19 November 2018 at 02:39:32 UTC, Stanislav Blinov
> wrote:
>> You're skimming the examples ;)
>
> I'm not saying your examples don't work, I'm trying to
> understand the minimum requirements. You said:
>
> "That's [constructors needing to be pure is] only for types
> with indirections (pointers), since `pure` guarantees that you
> do not mutate any global state."
>
> My example was only to show that:
> - a const constructor is insufficient for creating an immutable
> struct S
> - an immutable or pure constructor is sufficient for creating
> an immutable struct S
Yes, that's what I meant.
> You also showed that an inout constructor is sufficient too.
>
> I don't understand why not any constructor would work. After
> all:
>
> "value types are all copyable between mutable/const/immutable.
> So even if `return x + y` would yield a `const T`, you can
> still instantiate a T from it."
Because the rules still hold:
this(int) -> __ctor(T, int);
this(int) const -> __ctor(const T, int);
this(int) immutable -> __ctor(immutable T, int);
>> Recall that member functions (including constructors) are just
>> functions in disguise:
>> ...
>> what that boils down to, conceptually, is:
>
> I get what inout does know. But continuing on the constructor
> lowering, what strikes me is that:
>
> S __ctor(ref const S this, int x) {
> this.x = x; // allowed, while `this` is a const(S)!
> // return this; automatically inserted
> }
>
> Knowing that a constructor may mutate the const(this) or
> immutable(this) members, why can't a mutable(this) constructor
> be called on an immutable(this), *unless* it is pure (which
> seems irrelevant to me)?
Because it's not mutation, it's initialization. Just like you
write:
const int x = 1; // initializes a const int
x = 10; // error, can't mutate
...the first assignment to a member in a constructor is
initialization:
struct S {
int x;
this(int x) immutable {
this.x = x; // ok, initialization
this.x = 5; // error, can't mutate
}
}
When a ctor is `pure`, the compiler knows it doesn't mutate any
state other than the object's, so it allows conversion to all
three qualifiers.
What you can do, however, if you don't have an const/immutable
constructor, is call a mutable constructor explicitly, so long as
conversion is possible (i.e. value types):
struct S {
this(int) /* not immutable */ {}
}
immutable S x = 1; // error
immutable S x = S(1); // ok
More information about the Digitalmars-d-learn
mailing list