Topic: Proposal for Writing Generic Patterns
Author: mhw@minster.york.ac.uk
Date: 1995/07/04 Raw View
In article <3st8ou$aho@steel.interlog.com>,
Herb Sutter <herbs@interlog.com> wrote:
>
>SUGGESTED FEATURE
>=================
>
> A C++ mechanism for a base class to be able to specify a pointer to the
>current actual derived class.
I believe you can do this already using templates and rtti. In
particular, you can program in the mixin style using the following
idiom, which is similar to your proposed work-around:
template<class B>
class ten_percent_mixin {
public:
float value() const {
return dynamic_cast<B&>(*this)::B.value() * 1.10;
}
};
class weight {
float w;
public:
float value() const;
};
class weight10pc: public weight, public ten_percent_mixin<weight> {
public:
/* disambiguate multiple inheritance */
float value() const { return ten_percent_mixin<weight>::value(); }
};
Here the dynamic_cast<>() business is directly equivalent to
call-next-method in CLOS mixins. We get a pointer or reference
to the actual derived object which the member function was invoked
for. The scope operator is necessary to prevent recursion between
weight10pc::value() and ten_percent_mixin::value(). The syntax is
a little painful, but the approach is very general.
-Mark.
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Mark H. Wilkinson <mhw@minster.york.ac.uk> : Research student in user
University of York, England : interface management systems
Author: herbs@interlog.com (Herb Sutter)
Date: 1995/07/05 Raw View
In article <marnoldDAx9JK.11n@netcom.com>,
marnold@netcom.com (Matt Arnold) wrote:
>herbs@interlog.com (Herb Sutter) writes:
>> The problem is that (as far as I can see) we can't do this under the
draft
>>standard. A close attempt is to duplicate the core Singleton in its own
>>class (identically to the above):
>
>> class Singleton
>> {
>> static Singleton* Instance()
>> {
>> if (!_instance)
>> _instance = new Singleton; // outstanding issue here
>> return _instance;
>> }
>
>Huh?
>
>What's wrong with...
>
> template <class T>
> class Singleton
> {
> public:
> T& Instance()
> {
> static T t; // t will be constructed when Instance() is
> // called for the first time
> return t;
> }
> };
>
> class MySingle: public Singleton<MySingle>
> {
> // etc.
> };
>
> // etc. for other types
That's what I thought too when I wrote that. But consider:
class MySecondSingle : public MySingle { /*...breaks...*/ };
MySecondSingle does derive from Singleton, but from Singleton<MySingle>, not
from Singleton<MySecondSingle>. The pointer types will be wrong.
This can be worked around using parallel hierarchies, but it's tedious and
error-prone since if you don't see the error the code may well still compile
(though incorrectly).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Herb Sutter 2228 Urwin, Ste 102 voice (416) 618-0184
Connected Object Solutions Oakville ON Canada L6L 2T2 fax (905) 847-6019
Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/07/02 Raw View
herbs@interlog.com (Herb Sutter) writes:
>This article is a proposal (and a workaround, in case the proposal is
>rejected) for a suggested feature in C++.
I think the workaround is fine.
I don't think there's a need to add a new feature for this case.
>SUGGESTED FEATURE
>=================
>
> A C++ mechanism for a base class to be able to specify a pointer to the
>current actual derived class. For example, this might take the form of an
>actual_class keyword:
>
> class A {
> actual_class* Function() { return this; };
> };
>
> class B : public A {...}; // a B's Function() returns a pointer to B
>
> class C : public A {...}; // a C's Function() returns a pointer to C
I guess this is inspired by Eiffel's "like current" feature?
How is the compiler supposed to typecheck this?
For example, should the following be type-correct?
class A {
actual_class* Function() { return new A; };
};
[...]
>EXAMPLE: Implementing the Singleton Pattern
>===========================================
>
> Consider designing a class MySingle that we want to operate as a
>Singleton; that is, we want it to have one (or a controlled set of)
>instance(s) with a global point of reference. To implement it today, we
>supply the proper private static _instance pointer and public static
>Instance() function manually:
[...]
> However, this has a serious drawback: we have to respecify and
>reimplement these member variable and functions for every class we want to
>have behave as a Singleton (it may not be much work for this particular
>patterns, but it is for others)! This really doesn't seem to sit well
>with the OO goal of reuse. Instead, we would like to generalise the
>Singleton pattern into a class or template that we can just inherit from
>or instantiate, like this:
>
> class MySingle : public Singleton // an ideal way to write it
> {
> public:
> MyMethod (...);
> }; // complete definition, equivalent to above
But do you want one instance per singleton class, or just one instance
for the whole program? From your description above, it sounds like
MySingle::Instance() should return a different pointer to
YourSingle::Instance(). But with the suggested ideal way to write it,
you would only get one instance for all singletons, since there is only
one static `_instance' member. But that _can't_ be right, since
the `_instance' member is supposed to have a different type for each
derived class.
> The problem is that (as far as I can see) we can't do this under the draft
>standard. A close attempt is to duplicate the core Singleton in its own
>class (identically to the above):
>
> class Singleton
> {
> static Singleton* Instance()
> {
> if (!_instance)
> _instance = new Singleton; // outstanding issue here
> return _instance;
> }
>
> private:
> static Singleton* _instance; // omitting for now the issue
> // of how to define this
You're omitting a crucial issue here.
> };
>
> class MySingle : public Singleton
> {
> public:
> MyMethod (...);
> }; // not quite good enough
[...]
> The next obvious question is, What if we used templates?
Seems like the right solution to me.
> Can we derive what we want? Yes, albeit with somewhat inelegant code:
>
> // The following forward decl isn't required under BC++ 4.5 but may
> // be(?) in other compilers because of the nature of the next line.
> class MySingle;
> class MySingle : public Singleton<MySingle> // works in BC++ 4.5
The forward declaration should not be necessary for any compiler which
conforms to the draft standard (see 9.1/2).
I don't think the code is so inelegant.
> {
> public:
> MyMethod (...);
> }; // better, but somewhat convoluted
>
> (I have not yet encountered hidden problems with this construct; it
>appears to work properly in all cases I've used so far. However, part
>of my purpose in posting this article is to generate an aside discussion
>on whether this is guaranteed to be safe under the current draft standard.)
Yes, it should work.
> Still, we're prevented from just doing the natural derivation we want,
>namely the plain "class MySingle : public Singleton".
I don't think that could ever work, because of the unresolved problem
with the definition of the static data member.
> Granted, the workaround I've presented seems compelling -- if indeed it
>has no hidden dangers, for it does seem to be more than a little of a
>bootstrap to declare "class D : public B<D>". And it's true that the
>workaround avoids the outstanding issue of what to do about initialising the
>static variable in the above example.
Yep. The work-around is pretty nifty, really.
I wouldn't call it inelegant.
--
Fergus Henderson
fjh@cs.mu.oz.au
http://www.cs.mu.oz.au/~fjh
"The unexamined life is not worth living" - Socrates.
Author: herbs@interlog.com (Herb Sutter)
Date: 1995/07/04 Raw View
In article <9518314.22258@mulga.cs.mu.OZ.AU>,
fjh@munta.cs.mu.OZ.AU (Fergus Henderson) wrote:
>herbs@interlog.com (Herb Sutter) writes:
>
>>This article is a proposal (and a workaround, in case the proposal is
>>rejected) for a suggested feature in C++.
>
>I think the workaround is fine.
Actually even the workaround doesn't work, as it turns out.
Using "class MyClass : public Pattern<MyClass>" (to get derived class type
information into the base class) is _not_ a full workaround for an
actual_class keyword. Consider:
template<class T> class Pattern { /*...*/ };
class FirstClass : public Pattern<FirstClass> { /*...so far so good...*/ };
class OtherClass : public FirstClass { /*...oops...*/ };
With Pattern implemented as above to kludge the actual_class information,
only immediately derived classes behave properly. OtherClass now is derived
from a Pattern instantiated with MyClass, which is wrong (note this problem
would not appear if Pattern had real actual_class information). Note also
that:
class FirstClass : virtual public Pattern<MyClass> { /*...*/ };
class OtherClass : virtual public FirstClass, virtual public
Pattern<OtherClass> { /*...oops again...*/ };
..also doesn't work -- you just get two differently instantiated Pattern
classes. To fix this, you need to resort to a parallel class hierarchy:
Pattern FirstClassProto
| \ / |
| \ / |
| FirstClass OtherClassProto
\ /
\ /
OtherClass
So it's still not currently possible to "mix in" this kind of pattern
behaviour in such a way that a class and all of its descendants inherit the
pattern properly. Today it requires a workaround on top of a workaround:
first, the "class D : public B<D>" workaround to get the derived class
information into the base class, then the duplication of your entire class
hierarchy to make it work in the presence of more than one layer of
inheritance. Ugly; and worse, it's error-prone (because if you forget to
implement dual hierarchies the initial problem code above does still
compile, but doesn't behave properly).
That said, the more I've been thinking about what I want to be able to do in
this direction, the more I realise that I want not just actual_class (the
type of the actual most-derived class for the current object), but also an
actual_this (the real "this" for the current object, actually accessible in
a base class -- currently the base class' this is a pointer to the base
_part_ of the actual class, which may not be the same pointer value and will
certainly not be the corret type).
Otherwise I'm forced to:
a) use the "class MyClass : public Pattern<MyClass>" -- with a doubled-up
hierarchy -- workaround to get the actual_class into the Pattern; and
b) supply a pure virtual "This()" (that every derived class must override to
return its this, including specifying the proper return type) to get the
correct this pointer for the current object.
I currently simplify the latter by having a base "class NeedsThis { public:
NeedsThis* This() =0; };", and all classes that need the actual this for the
current object include it as public/virtual in their inheritance list.
However, it still requires _all_ derived classes to write their own
(always-identical) This() -- and heaven help them if they forget(!) and use
one of their concrete superclasses' This()es instead, for that will
definitely end up being a source of very-difficult-to-track-down bugs.
Error-prone, indeed! "Programmer discipline is no substitute for language
support." -- H.P. Sutter, 1994
>>SUGGESTED FEATURE
>>=================
>>
>> A C++ mechanism for a base class to be able to specify a pointer to the
>>current actual derived class. For example, this might take the form of an
>>actual_class keyword:
>>
>> class A {
>> actual_class* Function() { return this; };
>> };
>>
>> class B : public A {...}; // a B's Function() returns a pointer to B
>>
>> class C : public A {...}; // a C's Function() returns a pointer to C
>
>I guess this is inspired by Eiffel's "like current" feature?
Nope, as I don't know Eiffel, though I guess this means I'm not the first
to see this need. Matt Kennell (I think) mentioned the same thing...
clearly, then, this seems to be a useful construct to have if it is indeed
already present in other OO languages, like Eiffel and Sather.
>How is the compiler supposed to typecheck this?
>For example, should the following be type-correct?
>
> class A {
> actual_class* Function() { return new A; };
> };
No, for there's no implicit conversion from a base pointer to a derived
pointer. This would only be right when A is concrete and is itself the
actual class. The compiler can still apply all normal typechecking rules...
after all, remember that using actual_class is implicltly parameterising on
a type, and therefore the template rules will work fine.
>> class MySingle : public Singleton // an ideal way to write it
>> {
>> public:
>> MyMethod (...);
>> }; // complete definition, equivalent to above
>
>But do you want one instance per singleton class, or just one instance
>for the whole program? From your description above, it sounds like
>MySingle::Instance() should return a different pointer to
>YourSingle::Instance().
Indeed, this is what I had in mind. It would provide a way to inherit
fairly transparently from generic patterns, of the "I want my class to be a
Singleton" or "I want my class to be a Subject" variety.
>But with the suggested ideal way to write it,
>you would only get one instance for all singletons, since there is only
>one static `_instance' member. But that _can't_ be right, since
>the `_instance' member is supposed to have a different type for each
>derived class.
Exactly. Again, this is parameterising a type, just like in a template. I
elided this issue in the first article for clarity, but my view is that any
class with a static variable that is an actual_class* should have that
variable treated like it would be in a template: each class gets its own
copy, since the type of the variable changes with each class.
For example, something like:
class B { public: actual_class* _p; /*...*/ };
actual_class* B:_p = 0;
/* automatically generates B* B::_p = 0; */
class D1 : public B { /*...*/ };
/* automatically generates D1* D1::_p = 0; */
class D2 : public D1 { /*...*/ };
/* automatically generates D2* D2::_p = 0; */
>> The next obvious question is, What if we used templates?
>
>Seems like the right solution to me.
As noted above, it only works for directly-derived classes, and breaks
invisibly (i.e., still compiles but the wrong way, causing all sorts of bug
potential) otherwise unless you're very careful to implement a duplicate
class hierarchy (which even then is fragile IMO).
>> class MySingle : public Singleton<MySingle> // works in BC++ 4.5
It was only after I posted that I finally did find a reference to the "class
D : public B<D>" construct... it gets a four-line mention in "Design and
Evolution of C++", page 357. That's still the only reference I've seen to
it, with no detailed discussion about what it would be useful for. But at
least now I know it's guaranteed to be legal. :-)
>> Still, we're prevented from just doing the natural derivation we want,
>>namely the plain "class MySingle : public Singleton".
>
>I don't think that could ever work, because of the unresolved problem
>with the definition of the static data member.
Again, resolved by observing that actual_type, when used, is implicitly
parameterising on a type... and then we treat any uses the same way we
already do when explicitly parameterising a type in a template. It's quite
workable, indeed, and solves the problem elegantly -- avoiding the perils of
unsafe workarounds that require self-instantiated templates and bloated
class hierarchies.
Indeed, I'm more convinced now than before that actual_class information is
in fact needed (and an actual_this would be nice) to properly support
generic patterns. There is no (IMO acceptably safe) workaround using the
current draft C++ standard, as far as I know.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Herb Sutter 2228 Urwin, Ste 102 voice (416) 618-0184
Connected Object Solutions Oakville ON Canada L6L 2T2 fax (905) 847-6019
Author: herbs@interlog.com (Herb Sutter)
Date: 1995/07/04 Raw View
In article <3suqv6$ldv@martha.utk.edu>,
mbk@caffeine.engr.utk.edu (Matthew Kennel) wrote:
>
>This "actual_class" notion is denoted "like Current" in Eiffel
>and "SAME" in Sather. {The problem of pointers/types doesn't come up
>because most classes are reference types, and the notion of
>"the base portion" of a derived type doesn't have any interesting meaning
>in Sather or Eiffel}.
>
>It makes implementation inheritance & mixins more convenient: you can
>write more generic classes suitable as sources of inheritance with it.
>
>Yes: it is a good idea, and you can point to existing examples in
>other languages as testament to its utility.
Thanks for the reply. In another article I just posted to this thread, I
noted that the workaround I originally proposed isn't a workaround after
all. I'm more convinced than ever that we need actual_class (which would
really be just a special implicit compiler-supported type parameterisation)
to implement mixins and patterns well, there being no safe (IMO) workarounds
in the current draft C++ standard.
Details are in the other article.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Herb Sutter 2228 Urwin, Ste 102 voice (416) 618-0184
Connected Object Solutions Oakville ON Canada L6L 2T2 fax (905) 847-6019
Author: herbs@interlog.com (Herb Sutter)
Date: 1995/06/29 Raw View
This article is a proposal (and a workaround, in case the proposal is
rejected) for a suggested feature in C++. Because both the proposal and the
workaround are specifically intended to address writing generic patterns
(and other mixin designs) in existing OO languages, I'm crossposting to
comp.object and the patterns mailing lists for the benefit of those there
who might be interested in these ideas.
These solutions were derived independently; if they have been pointed out
before on the net or in the literature, I'm not aware of it, but I'd be
genuinely happy to be told otherwise. Corrections will be acknowledged in
these newsgroups.
SUGGESTED FEATURE
=================
A C++ mechanism for a base class to be able to specify a pointer to the
current actual derived class. For example, this might take the form of an
actual_class keyword:
class A {
actual_class* Function() { return this; };
};
class B : public A {...}; // a B's Function() returns a pointer to B
class C : public A {...}; // a C's Function() returns a pointer to C
(Aside: I am specifically NOT suggesting we allow a
base class to be able to specify the current actual
derived class, rather than just a pointer to it. First,
it seems unuseful: You would only use it to declare a
member variable or return type, which is not normally
meaningful for a class to do in terms of itself. Second,
it would cause serious difficulties for polymorphism:
Allowing a base class to store a member variable that can
change size in each concrete class would cause the base
portion of each derived class to change size also.)
I will present an example along with a tentative workaround using the
existing standard, for the purpose of gaining feedback from those more
experienced with these workarounds and determining whether or not the
workaround is truly safe.
MOTIVATION
==========
There are several important classes of designs that benefit from this
language support, specifically:
- generic design patterns;
- certain mixin styles.
I'll illustrate this using a well-known pattern documented in Gamma et
al's "Design Patterns" catalogue.
EXAMPLE: Implementing the Singleton Pattern
===========================================
Consider designing a class MySingle that we want to operate as a
Singleton; that is, we want it to have one (or a controlled set of)
instance(s) with a global point of reference. To implement it today, we
supply the proper private static _instance pointer and public static
Instance() function manually:
class MySingle
{
public:
static MySingle* Instance()
{
if (!_instance)
_instance = new MySingle;
return _instance;
}
private:
static MySingle* _instance;
// ...plus MySingle-specific attributes and behaviour, for example:
//
public:
MyMethod (...);
}
MySingle* MySingle::_instance = 0;
However, this has a serious drawback: we have to respecify and
reimplement these member variable and functions for every class we want to
have behave as a Singleton (it may not be much work for this particular
patterns, but it is for others)! This really doesn't seem to sit well
with the OO goal of reuse. Instead, we would like to generalise the
Singleton pattern into a class or template that we can just inherit from
or instantiate, like this:
class MySingle : public Singleton // an ideal way to write it
{
public:
MyMethod (...);
}; // complete definition, equivalent to above
The problem is that (as far as I can see) we can't do this under the draft
standard. A close attempt is to duplicate the core Singleton in its own
class (identically to the above):
class Singleton
{
static Singleton* Instance()
{
if (!_instance)
_instance = new Singleton; // outstanding issue here
return _instance;
}
private:
static Singleton* _instance; // omitting for now the issue
// of how to define this
};
class MySingle : public Singleton
{
public:
MyMethod (...);
}; // not quite good enough
The problem is that now applications can no longer call
MySingle::Instance()->MyMethod, because MySingle::Instance() returns a
Singleton*, not a MySingle*. We have not been able to provide full mixin
capability without requiring the application to use RTTI on the returned
pointer, as (dynamic_cast<MySingle*>MySingle::Instance())->MyMethod(),
which is quite ugly and error-prone. An alternative is to foist off the
work onto the MySingle programmer by making Singleton::Instance() virtual
and forcing him to override it in MySingle, but the function will be
identical except for the return type and it is clearly wasteful to force
the programmer to repeat it (and at any rate that still wouldn't address
the issue of reuse).
The next obvious question is, What if we used templates? It turns out
that we can implement a workaround by simultaneously deriving from a
template that is itself instantiated with the class being derived (if you
think that's a mouthful, it is, but read on):
template <class T>
class Singleton
{
static T* Instance()
{
if (!_instance)
_instance = new T; // use default ctor
return _instance;
}
private:
static T* _instance;
};
template<class T>
T* Singleton<T>::_instance = 0;
Can we derive what we want? Yes, albeit with somewhat inelegant code:
// The following forward decl isn't required under BC++ 4.5 but may
// be(?) in other compilers because of the nature of the next line.
class MySingle;
class MySingle : public Singleton<MySingle> // works in BC++ 4.5
{
public:
MyMethod (...);
}; // better, but somewhat convoluted
(I have not yet encountered hidden problems with this construct; it
appears to work properly in all cases I've used so far. However, part
of my purpose in posting this article is to generate an aside discussion
on whether this is guaranteed to be safe under the current draft standard.)
Still, we're prevented from just doing the natural derivation we want,
namely the plain "class MySingle : public Singleton". But, given
actual_class* type information, we could do it; that lack is the only
thing standing in the way in this case:
class Singleton
{
static actual_class* Instance()
{
if (!_instance)
_instance = new actual_class; // always uses default ctor
return _instance;
}
private:
static actual_class* _instance;
};
actual_class* Singleton::_instance = 0; // not semantically the same
// as in current draft;
// still needs to be resolved
Now we can go ahead the way we want, cleanly mixing in our pattern:
class MySingle : public Singleton
public:
MyMethod (...);
}; // ...and we're done.
SUMMARY
=======
The proposed feature's main advantage is that, for the price of just one
keyword, we are able to write reusable generic patterns using "natural"
derivation syntax. However, the use is not limited to patterns only; it
is useful in many cases where we would like to transparently mix in
behaviour from base classes, such as with the TProtectedObject class I
proposed two months ago here in comp.std.c++, which needs to know the size
of the actual concrete object that has been instantiated, namely
sizeof(actual_class).
Granted, the workaround I've presented seems compelling -- if indeed it
has no hidden dangers, for it does seem to be more than a little of a
bootstrap to declare "class D : public B<D>". And it's true that the
workaround avoids the outstanding issue of what to do about initialising the
static variable in the above example. Still, this article is meant to
provoke discussion, whether the proposal itself succeeds or is demonstrated
to be unworkable/unnecessary.
APPENDIX: Sample Implementation Using Existing Standard
=======================================================
//
// test.cpp
//
#include <iostream.h>
template<class T> class Singleton
{
public:
static T* Instance()
{
if (!_instance)
_instance = new T;
return _instance;
};
private:
static T* _instance;
};
template<class T> T* Singleton<T>::_instance = 0;
class MyFirstSingle : public Singleton<MyFirstSingle>
{
public:
void MyFirstMethod() { cout << "first" << endl; };
};
class MyOtherSingle : public Singleton<MyOtherSingle>
{
public:
void MyOtherMethod() { cout << "other" << endl; };
};
int main()
{
MyFirstSingle::Instance()->MyFirstMethod();
MyOtherSingle::Instance()->MyOtherMethod();
return 0;
}
----- Program Output (as compiled under BC++ 4.5):
first
other
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Herb Sutter 2228 Urwin, Ste 102 voice (416) 618-0184
Connected Object Solutions Oakville ON Canada L6L 2T2 fax (905) 847-6019
Author: marnold@netcom.com (Matt Arnold)
Date: 1995/06/29 Raw View
herbs@interlog.com (Herb Sutter) writes:
>This article is a proposal (and a workaround, in case the proposal is
>rejected) for a suggested feature in C++. Because both the proposal and the
>workaround are specifically intended to address writing generic patterns
>(and other mixin designs) in existing OO languages, I'm crossposting to
>comp.object and the patterns mailing lists for the benefit of those there
>who might be interested in these ideas.
[snip]
>SUGGESTED FEATURE
>=================
> A C++ mechanism for a base class to be able to specify a pointer to the
>current actual derived class. For example, this might take the form of an
>actual_class keyword:
> class A {
> actual_class* Function() { return this; };
> };
> class B : public A {...}; // a B's Function() returns a pointer to B
> class C : public A {...}; // a C's Function() returns a pointer to C
So, the "actual_class" return type is supposed to make A::Function() some
kind of virtual entity? In other words, it does a different thing based on
whether it is called with a pointer to B or C?
[snip]
> Consider designing a class MySingle that we want to operate as a
>Singleton; that is, we want it to have one (or a controlled set of)
>instance(s) with a global point of reference. To implement it today, we
>supply the proper private static _instance pointer and public static
>Instance() function manually:
[snip--stuff above Singleton classes that (somehow) new instances of
derived classes]
> The problem is that (as far as I can see) we can't do this under the draft
>standard. A close attempt is to duplicate the core Singleton in its own
>class (identically to the above):
> class Singleton
> {
> static Singleton* Instance()
> {
> if (!_instance)
> _instance = new Singleton; // outstanding issue here
> return _instance;
> }
Huh?
What's wrong with...
template <class T>
class Singleton
{
public:
T& Instance()
{
static T t; // t will be constructed when Instance() is
// called for the first time
return t;
}
};
class MySingle: public Singleton<MySingle>
{
// etc.
};
// etc. for other types
Isn't this kind of thing that templates are ideal for?
> The next obvious question is, What if we used templates? It turns out
>that we can implement a workaround by simultaneously deriving from a
>template that is itself instantiated with the class being derived (if you
>think that's a mouthful, it is, but read on):
Well, what you describe in the above paragraph is supposed to work. The
code I wrote above is supposed to work (and does work with a correctly
implemented compiler).
> Can we derive what we want? Yes, albeit with somewhat inelegant code:
> // The following forward decl isn't required under BC++ 4.5 but may
> // be(?) in other compilers because of the nature of the next line.
Then, those compilers need some more work. We don't need an extension
to the language (yet another feature for half-baked compiler vendors to
get wrong) to solve this following "inelegant" code (which woulndn't be
inelegant except for the concessions made for said crappy compilers).
> class MySingle;
> class MySingle : public Singleton<MySingle> // works in BC++ 4.5
> {
> public:
> MyMethod (...);
> }; // better, but somewhat convoluted
I don't think this is convoluted at all (once you remove the excess
compiler "consessions"). It looks just like my alternative above. It's
a nice, elegant, self-referential template. A pure and simple use of
existing language features.
>on whether this is guaranteed to be safe under the current draft standard.)
I believe it is. Furthermore, I believe, for this particular proposal, it
provides a viable alternative to your suggestion here (IMO, a better one
since it uses features already included in the language).
The last thing we need to do is add more language features to "help out"
those compilers that can't already correctly implement the current features
(specifically, template-related) of C++.
Your proposal to add a new keyword and functionality to C++, I think, is
overshadowed by the fact that you can already get what you want from the
language by using the "template" keyword and a few of extra angle-brackets.
The fact that certain compilers can't accept the code that implements this
solution (specifically, for this particular Singleton example) is a sign
of their shortcomings, not the language's.
>is useful in many cases where we would like to transparently mix in
>behaviour from base classes, such as with the TProtectedObject class I
>proposed two months ago here in comp.std.c++, which needs to know the size
>of the actual concrete object that has been instantiated, namely
>sizeof(actual_class).
Can't this also be done with the self-referential template technique? I
am not familiar with the TProtectedObject idea, but it sounds like it's
problem is similar to the one you are trying to address here. Again, it
seems to me that templates are the solution.
I think between templates and RTTI, the langauge already provides all the
power necessary to elegantly solve the types of problems you are addressing
with this proposal. Clearly, I think an elegant solution for the Singleton
problem already exists with the legal use of templates.
-------------------------------------------------------------------------
Matt Arnold | | ||| | |||| | | | || ||
marnold@netcom.com | | ||| | |||| | | | || ||
Boston, MA | 0 | ||| | |||| | | | || ||
617.389.7384 (h) 617.576.2760 (w) | | ||| | |||| | | | || ||
Windows C++ developer | | ||| 4 3 1 0 8 3 || ||
-------------------------------------------------------------------------
Author: mbk@caffeine.engr.utk.edu (Matthew Kennel)
Date: 1995/06/29 Raw View
Herb Sutter (herbs@interlog.com) wrote:
: These solutions were derived independently; if they have been pointed out
: before on the net or in the literature, I'm not aware of it, but I'd be
: genuinely happy to be told otherwise. Corrections will be acknowledged in
: these newsgroups.
: SUGGESTED FEATURE
: =================
: A C++ mechanism for a base class to be able to specify a pointer to the
: current actual derived class. For example, this might take the form of an
: actual_class keyword:
: class A {
: actual_class* Function() { return this; };
: };
: class B : public A {...}; // a B's Function() returns a pointer to B
: class C : public A {...}; // a C's Function() returns a pointer to C
: (Aside: I am specifically NOT suggesting we allow a
: base class to be able to specify the current actual
: derived class, rather than just a pointer to it. First,
: it seems unuseful: You would only use it to declare a
: member variable or return type, which is not normally
: meaningful for a class to do in terms of itself. Second,
: it would cause serious difficulties for polymorphism:
: Allowing a base class to store a member variable that can
: change size in each concrete class would cause the base
: portion of each derived class to change size also.)
This "actual_class" notion is denoted "like Current" in Eiffel
and "SAME" in Sather. {The problem of pointers/types doesn't come up
because most classes are reference types, and the notion of
"the base portion" of a derived type doesn't have any interesting meaning
in Sather or Eiffel}.
It makes implementation inheritance & mixins more convenient: you can
write more generic classes suitable as sources of inheritance with it.
Yes: it is a good idea, and you can point to existing examples in
other languages as testament to its utility.
: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
: Herb Sutter 2228 Urwin, Ste 102 voice (416) 618-0184
: Connected Object Solutions Oakville ON Canada L6L 2T2 fax (905) 847-6019