November 22, 2014
On Saturday, November 22, 2014 14:59:58 Eric via Digitalmars-d-learn wrote:
> On Saturday, 22 November 2014 at 09:57:55 UTC, anonymous wrote:
> > On Saturday, 22 November 2014 at 02:37:21 UTC, Eric wrote:
> >> I know I can make a class immutable, but the problem is I want to constrain a template parameter to only immutable types, and I want to use class types.
> >
> > template Foo(T : immutable Object)
> >
> > Accepts immutable(Object) and other immutable class types.
> > Rejects non-immutable class types like Object and const(Object),
> > and non-class types.
>
> Yes, but if I don't declare the class T as immutable, I don't think this constraint will work.

There is no such thing as an immutable class in D.

immutable class X
{
    ...
}

is equivalent to

immutable
{
    class X
    {
        ...
    }
}

or

class X
{
    immutable
    {
        ...
    }
}

Classes themselves are never immutable or const - or even mutable. Now, _instances_ of classes can be const or immutable. So, if you have

immutable X foo;

then foo is a reference to an immutable instance of X, but X itself is not and never will be immutable. So, if you have

template Foo(T : immutable Object)

then what that says is that if an instance of the type being passed in would implicitly convert to immutable Object, it will be accepted. That means that Foo!(immutable Bar) will work so long as either Bar is a class, or it's a struct or class which implicitly converts to immutable Object via alias this. And no types which aren't qualified as immutable will work with Foo.

However, in general, I'd suggest doing

template Foo(T)
    if(is(T == immutable))
{
}

because that specifically constrains that the type given to Foo is qualified
with immutable, avoiding any implicit conversion issues via alias this as
well as working with types which aren't classes. And if you actually want
T to be a class, you can do

template Foo(T)
    if(is(T == immutable) && is(T == class))
{
}

It's more verbose, but it avoids Foo instantiating due to an implicit conversion via alias this.

Regardless, you need to stop thinking of class declarations as being immutable or mutable or const. A class reference can be qualified with immutable or const so that the instance that it refers to is immutable or const, but classes themselves have nothing to do with mutability. Marking the reference as immutable

immutable X foo;

is what makes the type immutable not marking the class.

immutable class X
{
}

All marking the class as const or immutable is doing is qualifying all of its members as const or immutable, and that isn't going to work with any of the functions that are on Object itself (i.e. toString, toHash, opCmp, and opEquals) and is one of the reasons that we'd like to remove those functions from Object (letting subclasses then mark them with with whatever attributes are appropriate), but unfortunately, we have a ways to go before we can remove those functions from Object, since a number of things need to be done before we can do that (including fixing various compiler bugs and as well as the current AA implementation).

- Jonathan M Davis

1 2
Next ›   Last »