Singleton Pattern with struct

Artur Skawina art.08.09 at gmail.com
Thu Jan 24 09:14:20 PST 2013


On 01/24/13 17:52, ParticlePeter wrote:
>> Yes, but this can be broken by:
>>
>> import core.stdc.stdio : printf;
>>
>> struct Singleton  {
>>
>> private :
>>         this( int a = 0 ) {} ;
>>         static Singleton * s ;
>>
>> public :
>>         @disable this() ;
>>         static Singleton* instance()  {
>>                 if ( s is null )
>>                         s = new Singleton(0) ;
>>                 return s ;
>>         }
>>
>>         int val = 0 ;
>> }
>>
>> void main()
>> {
>>         Singleton s = * Singleton.instance;
>>         printf( "%d\n", s.val ) ; //
>>         Singleton.instance.val = 2 ;
>>         printf( "%d\n", s.val ) ; //0
>> }
>>
>> Here s is explicitly defined to be a struct object, not pointer (reference), so main.s is independent of further modification of Singleton.instance.
> 
> O.k. good to know, I'll try to avoid this. But one thing is still not clear,
> This method here ( my first approach ) does return a reference to an object on the heap, right ?
> 
> static ref Singleton instance()  {
>     if ( s is null )
>         s = new Singleton( 0 ) ;
>     return * s ;
> }
> 
> so when I use it with:
> auto another_s = Singleton.instance ;
> 
> Why is the s inside the struct and another_s not identical ?
> Afaik that is the purpose of the ref keyword ?

There currently are no reference variables in D [1]; the only way to get
a reference to something is via function arguments (including implicit
method ones) and function returns. So assigning a ref-return means a copy.

You can workaround it like this:

struct Singleton  {
private:
    this( int a = 0 ) {} ;
    static Singleton* s ;

public:
    @disable this();
    @disable this(this);
    static instance() @property {
        static struct Ref(T) { T* obj; ref g() @property { return *obj; } alias obj this; @disable this(this); }
        if ( s is null )
            s = new Singleton( 0 ) ;
        return Ref!(typeof(this))(s) ;
    }
    
    int val = 0 ;
}

though, that's not how I'd do it.

artur

[1] Classes don't count; they are a reference /types/.


More information about the Digitalmars-d-learn mailing list