Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

The Singleton Pattern

1 view
Skip to first unread message

Jim Barry

unread,
Mar 19, 1999, 3:00:00 AM3/19/99
to
There is a problem with using the singleton pattern on MSVC (and
possibly other compilers). Consider:

// Singleton.h

class Singleton {
Singleton();
~Singleton();
public:
static Singleton* Instance();
// ...
};

// Singleton.cpp

Singleton* Singleton::Instance() {
static Singleton instance;
return &instance;
}

The compiler says: error C2248: 'Singleton::~Singleton' : cannot
access private member declared in class 'Singleton'.

The Singleton destructor should remain private, to prevent attempts to
delete the singleton object. There was some discussion about this on
the group last year. My reading of The Standard is that it is a
compiler bug. Anyway, I have worked around it like this:

// Singleton.h

class Singleton {
Singleton();
~Singleton();
class Keeper; // forward-declare Keeper
friend class Keeper; // and make it a friend
public:
static Singleton* Instance();
};

// Singleton.cpp

class Singleton::Keeper {
friend class Singleton;
Singleton instance;
};

Singleton* Singleton::Instance() {
static Keeper keeper;
return &keeper.instance;
}

The key to making this work is declaring the nested class Keeper to be
a friend of its enclosing class Singleton. The syntax for doing that
is a little obscure and can be found in section C.11.3 of C++PL3, and
section 3.4.4.3 of The Standard.

--
Jim Barry, Thermoteknix Systems Ltd., Cambridge, UK.
http://www.thermoteknix.co.uk - Queen's Award for Export 1998
http://www.geocities.com/SiliconValley/2060

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

Chandrashekhar Mullaparthi

unread,
Mar 20, 1999, 3:00:00 AM3/20/99
to
Jim Barry wrote:
>
> There is a problem with using the singleton pattern on MSVC (and
> possibly other compilers). Consider:
>
> // Singleton.h
>
> class Singleton {
> Singleton();
> ~Singleton();
> public:
> static Singleton* Instance();
> // ...
> };
>
> // Singleton.cpp
>
> Singleton* Singleton::Instance() {
> static Singleton instance;
> return &instance;
> }
>
> The compiler says: error C2248: 'Singleton::~Singleton' : cannot
> access private member declared in class 'Singleton'.
>
> The Singleton destructor should remain private, to prevent attempts to
> delete the singleton object. There was some discussion about this on
> the group last year. My reading of The Standard is that it is a
> compiler bug. Anyway, I have worked around it like this:

I dont see why you call this a bug. You have to hide the destructor,
but provide some means to delete the object. You wont have that compiler
error if :

Singleton* Singleton::Instance() {
return new Singleton;
}
In the above case, implicitly the destructor will be invoked. In this
case
it wont be. So, you either dont delete the Singleton at all, or
If it is essential that your Singleton object go thru a proper
"destruction" sequence, you provide some other mechanism to invoke the
destructor and document its usage clearly.

Another problem with your approach of creating the Singleton object in
the
static area is, the invocation of operator delete on it is(I think it
is)
undefined. If I'm returning a pointer from any function, I'd rather
allot it on the heap so that there is no confusion to anyone.

The approach you have outlined below works, but it has the aformentioned
problem.

regards,
Chandru

>
> // Singleton.h
>
> class Singleton {
> Singleton();
> ~Singleton();
> class Keeper; // forward-declare Keeper
> friend class Keeper; // and make it a friend
> public:
> static Singleton* Instance();
> };
>
> // Singleton.cpp
>
> class Singleton::Keeper {
> friend class Singleton;
> Singleton instance;
> };
>
> Singleton* Singleton::Instance() {
> static Keeper keeper;
> return &keeper.instance;
> }
>
> The key to making this work is declaring the nested class Keeper to be
> a friend of its enclosing class Singleton. The syntax for doing that
> is a little obscure and can be found in section C.11.3 of C++PL3, and
> section 3.4.4.3 of The Standard.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Jim Barry

unread,
Mar 22, 1999, 3:00:00 AM3/22/99
to
Chandrashekhar Mullaparthi wrote in message
<36F29886...@eei.ericsson.se>...

>
>I dont see why you call this a bug.

Instance() is a member of Singleton and so should have access to all
private members of Singleton, including the destructor. The compiler
happens to implement destruction of local static objects by using
atexit handlers, but that should not change the access rules.

>Singleton* Singleton::Instance() {
> return new Singleton;
>}

Doesn't look much like the singleton pattern to me.

>Another problem with your approach of creating the Singleton object
in
>the
>static area is, the invocation of operator delete on it is(I think it
>is)
>undefined.

That is exactly why the destructor is private - to prevent deletion by
users of the singleton.

--
Jim Barry, Thermoteknix Systems Ltd., Cambridge, UK.
http://www.thermoteknix.co.uk - Queen's Award for Export 1998
http://www.geocities.com/SiliconValley/2060

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Martin von Loewis

unread,
Mar 22, 1999, 3:00:00 AM3/22/99
to
"Jim Barry" <jim....@bigfoot.com> writes:

> The Singleton destructor should remain private, to prevent attempts to
> delete the singleton object. There was some discussion about this on
> the group last year. My reading of The Standard is that it is a
> compiler bug.

It certainly is. It is surprising that the compiler doesn't complain
about the destructor being private: For the static variable, there
should be a destructor call, somewhere

> Anyway, I have worked around it like this:

[...]


> class Singleton::Keeper {
> friend class Singleton;
> Singleton instance;
> };
>
> Singleton* Singleton::Instance() {
> static Keeper keeper;
> return &keeper.instance;
> }

I'm *really* curious whether you compiler destroys the singleton at
the end of the program.

Regards,
Martin

Chandrashekhar Mullaparthi

unread,
Mar 23, 1999, 3:00:00 AM3/23/99
to
Jim Barry wrote:
>
> Chandrashekhar Mullaparthi wrote in message
> <36F29886...@eei.ericsson.se>...
> >
> >I dont see why you call this a bug.
>
> Instance() is a member of Singleton and so should have access to all
> private members of Singleton, including the destructor. The compiler
> happens to implement destruction of local static objects by using
> atexit handlers, but that should not change the access rules.

Ofcourse, Instance will have access to the destructor, but what are
you trying to say. The destructor for static objects will be invoked
after the last line of code you have written.

int main()
{

// blah

// Destructors of static objects get called here.
}

So, what has Instance() got to do with destruction of the Singleton?

regards,
Chandru

Jim Barry

unread,
Mar 26, 1999, 3:00:00 AM3/26/99
to
Chandrashekhar Mullaparthi wrote in message
<36F77EFC...@eei.ericsson.se>...

>
>Ofcourse, Instance will have access to the destructor, but what are
>you trying to say. The destructor for static objects will be invoked
>after the last line of code you have written.
>
>int main()
>{
>
>// blah
>
>// Destructors of static objects get called here.
>}
>
>So, what has Instance() got to do with destruction of the Singleton?

Everything. The static object exists within the scope of
Singleton::Instance(), therefore the destruction of the object should
be performed in the context of that scope. The fact that the
destructor is called after leaving main() is irrelevant. Consider:

class A
{
private:
~A() {}
friend class B;
};

class B
{
public:
static A a;
};

By your reasoning, the above should not compile because A::~A() is
inaccessible from global scope. However, it does compile because even
though the static instance of A is destroyed after leaving main(), the
destruction is performed with the same access as the object's
enclosing scope.

Incidentally, I have found another bug in MSVC. Remove the friend
declaration from the above code, and it still compiles.

The argument can be made more tersely:

class A {};
class B {
private:
static A a;
};

How would such code be legal if the compiler could only arrange to
destroy static objects using global scope access?

Regards

--
Jim Barry, Thermoteknix Systems Ltd., Cambridge, UK.
http://www.thermoteknix.co.uk - Queen's Award for Export 1998
http://www.geocities.com/SiliconValley/2060

Jim Barry

unread,
Mar 26, 1999, 3:00:00 AM3/26/99
to
Martin von Loewis wrote in message ...

>
>I'm *really* curious whether you compiler destroys the singleton at
>the end of the program.

Yes, it does.

Mat Noguchi

unread,
Mar 30, 1999, 3:00:00 AM3/30/99
to
Jim Barry wrote:
>
> class A
> {
> private:
> ~A() {}
> friend class B;
> };
>
> class B
> {
> public:
> static A a;
> };
>
> By your reasoning, the above should not compile because A::~A() is
> inaccessible from global scope.

You forgot to add

A B::a;

at file scope. MSVC then spits out:

error C2248: 'A::~A' : cannot access private member declared in class 'A'

> The argument can be made more tersely:
>
> class A {};
> class B {
> private:
> static A a;
> };

Actually, a class declaration w/ no destructor declaration will have a default
destructor created for it that is public.

MSN

Jim Barry

unread,
Mar 31, 1999, 3:00:00 AM3/31/99
to
Mat Noguchi wrote in message <370017E7...@glue.umd.edu>...

>
>You forgot to add
>
>A B::a;
>
>at file scope. MSVC then spits out:
>
>error C2248: 'A::~A' : cannot access private member declared in class
'A'

Ooops, yes, quite right. But in fact this rounds off my reductio ad
absurdum. The standard says in [class.access] section 11 paragraph 5:

"Access control for implicit calls to the constructors, the conversion
functions, or the destructor called to create and destroy a static
data member is performed as if these appeared in the scope of the
member's class."

So it seems clear to me that the compiler is getting it wrong, not
just for local-static variables, but for static member variables as
well.

>> class A {};
>> class B {
>> private:
>> static A a;
>> };
>
>Actually, a class declaration w/ no destructor declaration will have
a default
>destructor created for it that is public.

I am aware of that; my point was simply that B::a is not accessible
from global scope. If it was true that destruction of static variables
is performed from global scope, then the code could not be valid.

Regards

--
Jim Barry, Thermoteknix Systems Ltd., Cambridge, UK.
http://www.thermoteknix.co.uk - Queen's Award for Export 1998
http://www.geocities.com/SiliconValley/2060

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Spencer Simpson

unread,
Apr 1, 1999, 3:00:00 AM4/1/99
to

Jim Barry wrote in message ...

>There is a problem with using the singleton pattern on MSVC (and
>possibly other compilers). Consider:
>
>// Singleton.h
>
>class Singleton {
> Singleton();
> ~Singleton();
>public:
> static Singleton* Instance();
> // ...
>};
>
>// Singleton.cpp
>
>Singleton* Singleton::Instance() {
> static Singleton instance;
> return &instance;
>}
>
>The compiler says: error C2248: 'Singleton::~Singleton' : cannot
>access private member declared in class 'Singleton'.


Sounds like a compiler bug to me, but why do you use a pointer?
Seems to me the following is better:

// Singleton.h

class Singleton
{
Singleton();
~Singleton();
public:

static Singleton& Instance()
{
static Singleton instance;
return instance;
}
// ...
};


Hope this helps

Andrei Alexandrescu

unread,
Apr 2, 1999, 3:00:00 AM4/2/99
to
Spencer Simpson <map...@erols.com> wrote in message
news:7dvqmb$8sv$1...@autumn.news.rcn.net...

> class Singleton
> {
> Singleton();
> ~Singleton();
> public:
> static Singleton& Instance()
> {
> static Singleton instance;
> return instance;
> }
> // ...
> };

You forgot to make the copy constructor private. With your implementation, a
perverse user can do:

Singleton * pSneaky = new Singleton(Singleton::Instance());

Andrei

Spencer Simpson

unread,
Apr 5, 1999, 3:00:00 AM4/5/99
to

Andrei Alexandrescu wrote in message <7e2itn$5c...@news.okidata.com>...

>Spencer Simpson <map...@erols.com> wrote in message
>news:7dvqmb$8sv$1...@autumn.news.rcn.net...
>> class Singleton
>> {
>> Singleton();
>> ~Singleton();
>> public:
>> static Singleton& Instance()
>> {
>> static Singleton instance;
>> return instance;
>> }
>> // ...
>> };
>
>You forgot to make the copy constructor private. With your implementation,
a
>perverse user can do:
>
>Singleton * pSneaky = new Singleton(Singleton::Instance());


Ouch. Good point. And operator new, and the assignment operator.
You could make an argument that this is still better than the pointer
version.

Best regards

James...@dresdner-bank.com

unread,
Apr 8, 1999, 3:00:00 AM4/8/99
to
In article <7dvqmb$8sv$1...@autumn.news.rcn.net>,

Spencer Simpson <map...@erols.com> wrote:
>
> Jim Barry wrote in message ...
> >There is a problem with using the singleton pattern on MSVC (and
> >possibly other compilers). Consider:
> >
> >// Singleton.h
> >
> >class Singleton {
> > Singleton();
> > ~Singleton();
> >public:
> > static Singleton* Instance();
> > // ...
> >};
> >
> >// Singleton.cpp
> >
> >Singleton* Singleton::Instance() {
> > static Singleton instance;

> > return &instance;
> >}
> >
> >The compiler says: error C2248: 'Singleton::~Singleton' : cannot
> >access private member declared in class 'Singleton'.
>
> Sounds like a compiler bug to me,

It is a compiler bug according to the standard, but it is a point which
was only cleared up in the last or the next to last meeting before the
final standard, so some compilers may still not be up-to-date.

--
James Kanze mailto: James...@dresdner-bank.com
Conseils en informatique orientée objet/
Beratung in objekt orientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49 (069) 63 19 86 27

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own

Leonid Ilyich Vaisman

unread,
Apr 13, 1999, 3:00:00 AM4/13/99
to
Spencer Simpson <map...@erols.com> wrote in message
news:<7e99fg$h52$1...@autumn.news.rcn.net>...
<...snip...>
> >> static Singleton& Instance()
> >> {
> >> static Singleton instance;
> >> return instance;
> >> }
> >> // ...
> >> };
<...snip...>> You could make an argument that this is still better than the
pointer
> version.

Is it commonly presumed in Singleton pattern that it is deleted in the end
of the program?
In my designs, I had cases when destruction of some singleton had to be
performed before destruction of other object. Hence, there were one or more
objects responsible for singleton destruction - and here comes singleton
implementation with static pointer... Are there problems in such design?

Leonid Ilyich Vaisman (ilyich at odin co il)

Jim Barry

unread,
Apr 15, 1999, 3:00:00 AM4/15/99
to
Leonid Ilyich Vaisman wrote in message
<7es7ii$jv6$1...@news2.inter.net.il>...

>
>Is it commonly presumed in Singleton pattern that it is deleted in
>the end of the program?
>In my designs, I had cases when destruction of some singleton had
>to be performed before destruction of other object. Hence, there were
>one or more objects responsible for singleton destruction - and here
>comes singleton implementation with static pointer... Are there
>problems in such design?

In that case I think the singleton instance would need to be a static
member, defined in the same translation unit as, and after the
(static) object(s) it depends on. There are no guarantees about order
of initialisation between different translation units, though there
are tricks to get around that (see Stroustrup C++PL3, 21.5.2).

One advantage of using a local static (as in my original posting) is
that the singleton is only initialised it if is used. If you know that
it definitely will be used then a local static offers no particular
advantage there, other than possibly quicker program startup. The
other consideration is that you might not have enough information at
program startup to initialise the singleton.

If you wanted a singleton with the same lifetime as main, then you
could do something like this:

// Singleton.h
class Singleton {
friend int main();
Singleton();
Singleton(Singleton const&); // hide copy c'tor
~Singleton();
static Singleton* instance;
public:
// Could return a reference here - semantically equivalent
static Singleton* Instance();
};

// Singleton.cpp
Singleton* Singleton::instance;
Singleton::Singleton() { instance = this; }
Singleton::~Singleton() { instance = 0; }
Singleton* Singleton::Instance() { return instance; }

// Main.cpp
int main() {
Singleton instance;
// ...
}

Of course, with this arrangement the singleton object is not available
during program startup or termination, so you could not use it in
constructors or destructors of static objects.

--
Jim Barry, Thermoteknix Systems Ltd., Cambridge, UK.
http://www.thermoteknix.co.uk - Queen's Award for Export 1998
http://www.geocities.com/SiliconValley/2060

0 new messages