const and immutable member variables in classes

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Feb 2 19:05:36 PST 2016


On Tuesday, February 02, 2016 18:14:50 H. S. Teoh via Digitalmars-d-learn wrote:
> On Tue, Feb 02, 2016 at 05:49:00PM -0800, Jonathan M Davis via Digitalmars-d-learn wrote:
> > On Tuesday, February 02, 2016 14:48:03 Ali Çehreli via Digitalmars-d-learn wrote:
> > > const and immutable members make structs non-assignable:
> [...]
> > > That's why I've been avoiding them altogether. However, considering
> > > that there is no default-assignment for classes, there is no problem
> > > with using const or immutable members with classes, right?
> >
> > Default initialization isn't really the issue. It's assignability in
> > general. Even if you @disabled default initialization in a struct,
> > then having a const or immutable member would be annoying, because you
> > couldn't assign it another value later. But in any case, no, classes
> > don't have that problem (at least not normally), because you don't
> > assign to them. You just assign to their references. So, you don't
> > normally run into an issue where you're trying to overwrite the state
> > of a class object and aren't able to.
> [...]
>
> In general, I find const/immutable members more of a pain than anything
> else. Such aggregates are extremely cumbersome to work with, and
> besides, I've yet to come up with a conceptually-clean mental model of
> just what kind of semantics exactly an aggregate with a const/immutable
> member "ought" to have.
>
> *Reference* members to const/immutable data make sense -- these include
> string members, for example, as immutable(char)[]. It's not a problem
> because the reference itself is mutable, just not what it refers to.
>
> It's also not a problem when the entire aggregate is const or immutable,
> e.g., when passing by const to a const member, for example. By
> transitivity, it's clear that the entire aggregate is const / immutable,
> so every member is also transitively so.
>
> But when a member itself is const or immutable, things become really
> icky. A mutable instance of a struct with a const member is in a weird
> mixed state of being partially mutable and partially not. You can never
> create an instance of the struct that's fully mutable, so even when
> given a mutable instance, you can't overwrite it, you can't assign to
> it, etc..
>
> It's also unclear what guarantee the const/immutable member is supposed
> to provide.  In the case of an argument to a function, it's clear that
> const means the callee promises not to modify, and immutable means the
> caller (and callee) promise never to modify. But what promise does a
> const/immutable member give? That nobody can ever modify, except this
> only applies to that member and the rest of the aggregate may still be
> mutable? It's rather unclean semantics that leads to all sorts of
> needlessly convoluted cases, with hard-to-grasp results, and it's hard
> to think of a use case that requires such a construct, that can't be
> done some other way.

Well, in principle, if you have a member that's going to be initialized on
construction and then never mutated, having it be const or immutable would
be desirable, but for all of the reasons that you're listing, to do so with
structs is ultimately a bad idea. Things just get weird and annoying when
you have const or immutable members in mutable structs. But under normal
circumstances, member variables of classes don't have that problem, because
you don't normally ever try to overwrite the state of the whole class
object.

But for some reason, I keep seeing folks post stuff where they've tried to
have const or immutable members of structs. I don't know if the folks who do
so typically give up on it, but I usually tell folks not to do it because of
all of the problems it causes.

- Jonathan M Davis




More information about the Digitalmars-d-learn mailing list