immutable singleton pattern with static opCall

Steven Schveighoffer schveiguy at yahoo.com
Mon Jun 28 05:19:53 PDT 2010


On Mon, 28 Jun 2010 08:07:40 -0400, Justin Johansson <no at spam.com> wrote:

> Steven Schveighoffer wrote:
>> On Sat, 26 Jun 2010 20:19:44 -0400, Michal Minich  
>> <michal.minich at gmail.com> wrote:
>>
>>> On Sun, 27 Jun 2010 09:36:04 +0930, Justin Johansson wrote:
>>>
>>>> immutable class Foo
>>>> {
>>>>     static private Foo instance;
>>>>
>>>>     static this() {            // line 9
>>>>        instance = new Foo;
>>>>     }
>>>>
>>>>     static Foo opCall() {        // line 13
>>>>        return instance;
>>>>     }
>>>> }
>>>>
>>>> test.d(9): Error: function test.Foo._staticCtor2 without 'this' cannot
>>>> be const/immutable
>>>> test.d(13): Error: function test.Foo.opCall without 'this' cannot be
>>>> const/immutable
>>>
>>> there is bug report on this subject
>>>
>>> http://d.puremagic.com/issues/show_bug.cgi?id=3598
>>>
>>> Your example also uses static variable, which was not considered in the
>>> bug report. This makes things more complex to design properly, because  
>>> it
>>> seems now that one does not want static functions to be affected by
>>> immutable attribute of class, but it should affect static data...
>>  static variables inside an immutable class should be immutable.  That  
>> was considered in the bug report and purposefully left out.
>>  The issue is that the compiler incorrectly labels static *functions*  
>> as immutable which makes no sense, static functions cannot be immutable  
>> ever.  Static data can be.
>>  BTW, you can work around this problem like this:
>>  class Foo
>> {
>>    static immutable instance; // no need to make private, it can never  
>> change
>>     static this() {
>>       instance = new Foo;  // not sure if this works, you may have to  
>> cast.
>>    }
>>     static immutable(Foo) opCall() {
>>       return instance;
>>    }
>>     immutable:
>>     // member functions
>> }
>>  -Steve
>
> Thanks Steve.
>
> btw. The reason I marked the static instance member as private
> was simply to enforce stylist use of Foo() rather than Foo.instance

Yuck Foo().xyz :)

But, whatever floats your boat.

>
> You guess is correct; I found that you have to use a cast with
> instance = new Foo
> but then I discovered that you can avoid the cast by writing
> a trivial constructor marked with immutable, i.e.
> immutable this {}

Ah, that is good.  However, I was also unsure if a static immutable could  
be set inside a static constructor.  That is also good, immutable has  
definitely gotten a lot easier to use!

> Though this doesn't reduce the headcount of the uses of the immutable
> keyword, I think it looks nicer than a cast.  Your idea of immutable:
> though is good for the remainder of the member functions (and the
> trivial ctor).

I have a feeling that the afore mentioned bug will eventually be fixed,  
and at that point, you can just make Foo an immutable class with no issues.

>
> My immutable singleton pattern now looks like this :-)
>
>
> class Foo
> {
>     // following marked private for stylistic enforcement
>     static immutable private Foo instance;
>
>     static this() {
>        // following works without cast thanks to immutable ctor
>        instance = new Foo;
>     }
>
>     static immutable(Foo) opCall() {
>       return instance;
>     }
>
> immutable:
>    this() {}
>
>    // more immutable member function decls following
>    // ..
> }

To go one step further, if you want it to truly be a singleton type, you  
should mark the constructor private.

-Steve


More information about the Digitalmars-d mailing list