On 05/21/2016 03:36 PM, chmike wrote:
Note however that it doesn't work with immutable. It only works with
constant. I guess this is because immutable is "stronger" than const. I
determined that only const was supported by looking at Rebindable's code.

Here is the code that finally works as I want. The flyweight pattern is
thus well supported with the exception that switch can't be used.

using static functions to get the Infos.one also allow to implement lazy
object instantiation.
[...]
I wasn't indeed using Rebindable correctly and it support only const
objects, not immutable objects.

I think your conclusion is wrong. Works fine if you add a couple `immutable`s (and change one `IInfo` to `Info`):

----
import std.stdio;
import std.typecons;


interface IInfo {
    string toString() const;
}

alias Rebindable!(immutable IInfo) Info; // Compiles just fine.

class Infos {

    static class Obj : IInfo
    {
        this(string msg) immutable { this.msg = msg; }
        private string msg;
        override string toString() const { return msg; }
    }

    static Info one()
    {
        static auto x = Info(new immutable Obj("I'm one"));
        return x;
    }
    static Info two()
    {
        static auto x = Info(new immutable Obj("I'm two"));
        return x;
    }
}

void main()
{
    Info x1;
    Info x2 = Infos.one;

    assert(x1 is null);
    assert(x2 !is null);
    assert(x2 is Infos.one);
    assert(x2 == Infos.one);

    x1 = x2;
    assert(x1 is x2);
    assert(x1 == x2);

    assert(x1 is Infos.one);
    assert(x1 == Infos.one);

    writeln(x1);

    Info x3 = Info(new immutable Infos.Obj("I'm one"));
    assert(x1 !is x3);
    assert(x1 != x3); // Because there is no opEqual for deep equality test

    Info
        o1 = new immutable Infos.Obj("I'm one"),
        o2 = new immutable Infos.Obj("I'm one");
    assert(o1 !is o2);
    assert(o1 != o2); // What I need for the flyweight pattern

    /* -- Doesn't compile : x1 is not a string or integral value
    switch(x1)
    {
    case Infos.one: writeln("case Infos.one"); break;
    default: writeln("default"); break;
    }
    */
}
----

I thought marking the constructor `pure` would make it possible to implicitly convert a mutable `new` expression to immutable, but I couldn't get that to work. That would avoid all those `immutable`s. I'm probably forgetting something here.

Reply via email to