Topic: current_class: Submitted Public Comment


Author: p150651@proffa.cc.tut.fi (Pulkkinen Esa)
Date: 1995/07/17
Raw View
In article <3u3aa4$slg@steel.interlog.com>,
Herb Sutter <herbs@interlog.com> wrote:
>Let me put it another way:  Is there any benefit to allowing the user to
>override it (that can't be done with existing template functionality)?  When
>would we want a template parm which defaults to current_class be something
>other than current_class, and still not violate base class assumptions?
>
I tried to make an example, but couldn't come up with anything
that couldn't be made with existing template functionality. I was
thinking something like using multiple template parameters defaulting
to current_class in one function's definitions, and then allowing
(for example) overriding them one at a time in derived classes to
provide means to gradually fix the type parameters. But as said,
every example I could provide could already be made with
ordinary templates or using virtual functions.

>Very interesting!  I would offer a slight refinement (though I suspect that
>you meant something along these lines anyway): Define Register_server itself
>as a template, and then:
>
>  Register_server<X> X<T>::id(&X::Create);
I assume you meant:
   Register_server<X> X<T>::id(&T::Create);

>Good point; I made a similar observation.  But let me know what you think of
>the other argument I make in that other article, namely that while we
>could require a declaration (e.g., "template<current_class>")
>to make the compiler's job easier (knowing which classes/functions
>use it based on their declarations
>alone), I'm leaning more strongly against having it be a default to a usual
>template argument since in several important ways it does not behave
>like one (e.g., it isn't meaningful in function templates).

I think some kind of notification for the compiler is a minimum
requirement. I'm now more critical about the default argument, since
I found an example leading to a paradox (infinite virtual function table)
when allowing the user to override the template argument:

  class X
  {
     template <class T=current_class>
     void do_f() { f(dynamic_cast<T*>(this)); }
  };
  class Y : public X
  {
     template <class T=current_class>
     void do_f() { g(dynamic_cast<T*>(this)); }
  };

To implement this and overriding the default argument
assumes potentially infinite virtual function table.
Consider calling the do_f function when given a pointer:
  X* obj=new Y;

  obj->do_f(); // calls g(Y*) (dynamic)
  obj->X::do_f(); // calls f(Y*) (dynamic)
  obj->template do_f<X>(); // calls g(X*) (still dynamic!, requires
                           //              a virtual function table
                           //              entry for each possible
                           //              template argument)
  obj->template X::do_f<X>(); // calls f(X*) (static call)

--
   Esa Pulkkinen                       | C++ programmers do it virtually
   E-Mail: esap@cs.tut.fi              | always with classes, resulting
   WWW   : http://www.cs.tut.fi/~esap/ | in multiple inheritance.





Author: herbs@interlog.com (Herb Sutter)
Date: 1995/07/12
Raw View
In article <3tu472$7he@usenet.rpi.edu>,
   vandevod@avs.cs.rpi.edu (David Vandevoorde) wrote:
>In article <3ttt91$oqu@steel.interlog.com>,
>Herb Sutter <herbs@interlog.com> wrote:
>>>[ in the following, multiple versions of the regular function f(X) are
>>>  assumed to exist ]
>>>
>>>>  class A {
>>>>  public:
>>>>      void do_f()  { f(dynamic_cast<current_class*>(this)); }
>>>>  };
>[...]
>>Mmm, now I see where you're coming from.  Good point.  In another article in
>>this thread, Esa wrote:
>>
>>>class X
>>>{
>>>  template <class T=current_class> void do_f(void)
>>>  {
>>>    f(dynamic_cast<T*>(this));
>>>  }
>>>};

>>A small concern: this form would require a minor change to existing rules to
>>prevent users from filling in that (now-visible) template parm.
>
>Well, I had the same reflex at first and thus thought the "better
>syntax" should be:
> template<this_class> ...

(Note: I'm going to argue strongly for this in the rest of this article,
though I'll call the declaration "template<current_class>".)

>but when I thought it over, I saw no reason to prevent users from
>specifying the 'T' in
> template<class T = this_class> ...

Hmmm!  I'm afraid I definitely do want to prevent users from specifying or
even knowing about the template; besides the fact that a user's specifying it
manually would break the whole scheme (and hence renders the approach
fragile), it would cause all sorts of derivation problems (as you point out
later on, see below for more discussion).

>BTW, we could avoid the introduction of a new keyword with:
> template<class T = this> ...

Urk.  I see your point, but isn't C++ already replete with overloaded keywords
(e.g., static)? :-(  I can see the confusion already: "But 'this' is a pointer
to a type, yet here it's the actual type...?"

At any rate, I've been thinking over the whole scheme (of introducing it as an
explicit template), and there seems to me to be one very major problem from
which all of the afore- and later-mentioned problems flow:

   The current_class type cannot be used exactly like a regular template
   type.  It has more restrictions.

Specifically:

   a) a class writer may not declare a member variable of type current_class
      (see the public comment's Questions & Answers section);

   b) (as above) the template may never be supplied explicitly, but rather
      the compiler is responsible for supplying it in this and all subsequent
      (instantiated and derived) classes;

   c) current_class makes sense only within classes, not within standalone
      functions, and so could not be used in standalone function templates.

Of these, (a) is quite unintuitive if current_class is expressed as a normal
templated type.  Yet we would need additional special rules to prevent the
class writer from instantiating a member variable of type current_class
because it will change size in every derived class and "would wreak havoc with
existing rules" (as I put it in the public comment).  (Yes, there are ways
around it, at the expense of compiler complexity: e.g., we could require the
compiler to transparently change member variables of type current_class to be
pointers only, automatically new'd in the ctor and deleted in the dtor, which
would completely solve the size problem but which puts yet another burden on
compiler writers -- indeed, why would an object reasonably want to contain
another object of the same class?  If it did, the recursion would seem to be
infinite, making the class uncompilable/unrepresentable.)

At any rate, it seems to me that since current_class would not behave like a
normal explicit template, it probably should not be one.

That said, one of the original reasons for trying this alternative was to give
the compiler more information: specifically, to let the compiler know when
current_class implicit-template information was being used.  In this case, I
like your original suggest ('way above there):

   template<current_class> /* class or member function declaration follows */

That way: a) the compiler knows the class/function uses current_class info; b)
the client code cannot accidentally/ill-advisedly supply it (and no extra
rules to support this would be required, other than skipping the optional
current_class entry in the template parm list if it appears); c) in the actual
code, where current_class is used it always actually appears as that, as
"current_class" (not as some other parameterised type where you have to go
back to the header and remember which of the template args was current_class),
making things more readable.

Does this compromise sound reasonable?  The current_class template is still
"mostly" implicit, other than that now it is declared.  I suppose it should be
an error for a user to declare "template<current_class>" and then not use it,
since just declaring current_class invokes template (and vtable? haven't quite
thought that one through yet) overhead.

> template<typename T = this>
> struct singleton {
  /* elided */
> };
>
> struct B1: singleton {
> };
>
> template<typename T = this>
> struct B2: singleton<T> {
> };
>
> struct D1: B1 {
> };
>
> struct D2: B2 {
> };
>
> f() {
>     D2* d2 = D2::instance(); // OK
>     D1* d1 = D1::instance(); // Not OK, requires a cast.
> }
>
>Note that D2 is derived from B2<D2> which in turn is derived from
>singleton<D2>. D1 on the other hand, is derived from the non-template
>class B1 which has a base class singleton<B1>.

Right, this is the problem... it's only a slight improvement over what we can
already do today, but it still requires programmer interference (er, I mean,
"discipline" <g>) to propagate the template and get it right.  That's why I
really don't like it.

To prove that we can already do this much today, consider (using the existing
language only, modifying your example slightly):

 template<typename T>
 struct singleton {};

 template<typename T = B2>   // <--- the interesting part
 struct B2: singleton<T> {}; //      each derived class must do this

 template<typename T = D2>   // <--- again
 struct D2: B2<T> {};

 f() {
     D2* d2 = D2::instance(); // OK
 }

All I've done is replace the default for the template arg with the class
itself, for each derived class.  Yet this is equivalent to your approach above
for implementing current_class, and so that approach actually doesn't seem to
buy us anything in this example: we can achieve similar complexity today,
without that particular implementation of a current_class keyword.  The
current_class keyword was supposed to save us from requiring subclasses to do
these kinds of gymnastics, and it can, but it seems not with this kind of
implementation.  This mechanism uses template default args to propagate
derived-class information up the inheritance tree, class by class.

However, you've now demonstrated something important, namely one detail I
claimed in the comment seems to be wrong: Using deep derivation and
propagating current_class-like information manually does not after all seem to
preclude polymorphism between the derived types (you just have to rely on
default args and never forget to supply them properly for each class, as
above).  Singleton, B2, and D2 can still be used polymorphically in this
scheme.

(Aside: However, perhaps this scheme demonstrates a simple and viable compiler
implementation of current_class; could not the compiler be given the job of
doing exactly this and getting the types right?  Just a thought on a possible
implementation.)

However, even with that problem gone, it relies completely on programmer
interfe-- er, that is, discipline -- and my broken record still plays on:
"Programmer discipline is a poor substitute for language support." (HS, 1994)
This still doesn't give us true mixinability, and there's no real reason why
we shouldn't be able to mix in this way in C++, simply "struct B2: singleton
{}; struct D2: B2 {};" etc. without having to be impacted by implementations
upstream.

Heck, consider: What if a base class currently doesn't use current_class info
and we have derived classes like "struct Derived: Base"?  All's well, but now
what if the base is changed because it needs current_class for a certain
function -- ought we to be forced to go through every class that derived from
Base (directly or indirectly) and supply this template and retrofit the
implementations?  That's what current_class is supposed to give us:
transparent reusability, without base changes careening madly through the
object model.  If it were up to the compiler, fine, it's a recompile; but if
we do it manually it's up to us to catch and fix all of these repercussions,
and heaven help us if we miss one because the omission might not even flag a
warning.

>You're welcome. This thread is a lot more stimulating than many I've
>seen in the comp.*.c++ groups.

Thanks, and regards,

Herb


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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/13
Raw View
In article <3tvefo$41j@peippo.cs.tut.fi>,
   esap@cs.tut.fi (Pulkkinen Esa) wrote:
>In article <3ttsia$oqu@steel.interlog.com>,
>Herb Sutter <herbs@interlog.com> wrote:
>
>>2) The template parm still should not be entered by any client code... if
>>there are other templated parms, perhaps the one defaulting to current_class
>>should always be last and never be instantiable directly by the user.  IOW,
>>in your example the user would always write something like "X::do_f()",
never
>>"X::do_f<??>()".  If there were additional parameters, like:
>>
>>    template<class A, class T=current_class> void do_f(void) { /*...*/ };
>>
>>then the user would always write something like "X::do_f<MyClass>()", and
>>again never be allowed to supply the parameter defaulting to current_class.
>
>I can't see any reason why the template parameter couldn't be provided
>by the user (this was pointed out already in other thread),
>current_class (clearly?) just can't be used as an explicit template
>parameter, only as a default.

My response to that is probably on its way to you now.  Basically, I'm highly
sceptical because allowing the user to supply the parm may break assumptions
(esp. that the parm is in fact the current_class -- the user could conceivably
throw something else in there, perhaps not even inherited from us... like
int!).  The purpose of current_class was to let base classes know the exact
type of the derived class in which they are currently being used; there would
have to be a good reason to open this up to subversion.

Let me put it another way:  Is there any benefit to allowing the user to
override it (that can't be done with existing template functionality)?  When
would we want a template parm which defaults to current_class be something
other than current_class, and still not violate base class assumptions?

>>3) That said, sometimes classes themselves (not just member functions)
>>need to
>>know current_class, and therefore you might have "template<class
>>T=current_class> class X { /* ...uses current_class info, say to store a
>>pointer...*/ };".
>
>This is a good observation. First application that comes to my mind is
>registration of classes through inheritance:
>  template <class T=current_class>
>  class X
>  {
>    static Register_server id;
>  public:
>    static current_class *Create() { return new T; }
>    // ...
>  };
>  template <class T=current_class>
>  Register_server X<T>::id( &X::create );
>
>  class Y : public X { };
>   // nothing else needed, there is an individual id
>   // object in Y also
>
>Now, this is a powerful technique, with proper definition of Register_server,
>allows the base class (or code using the base class) to get information
>about (all) derived classes, create objects of derived classes they
>have never heard of, and impose various constraints to them
>(like if you declared a static (data or function) member
>but left it undefined except for the base class, all derived classes
>,whether directly or indirectly inherited, would have to implement it.).

Very interesting!  I would offer a slight refinement (though I suspect that
you meant something along these lines anyway): Define Register_server itself
as a template, and then:

  Register_server<X> X<T>::id(&X::Create);

That way Register_server's ctor can throw all id's derived from X into the
same ServerRegistry<X> which can then be queried by X (or anyone else knowing
about X, for that matter).  This way Register_server and ServerRegistry are
generic, and any future classes that want to use them, as X does today, get
their own entries/instantiations.

Thanks very much for this example: this is another powerful technique that
can't be done without current_class information, and I'll add it to future
versions of the public comment if they're ever needed.

>btw, to respond to the another thread that suggested using 'this'
>instead of 'current_class' to prevent inventing a new keyword:
>I find 'this' keyword somewhat confusing, since it has traditionally
>been used as a pointer, and it already has a meaning as template
>default argument. I would think 'virtual' would be better choice,
>if inventing a new keyword is such a bad thing.

Good point; I made a similar observation.  But let me know what you think of
the other argument I make in that other article, namely that while we could
require a declaration (e.g., "template<current_class>") to make the compiler's
job easier (knowing which classes/functions use it based on their declarations
alone), I'm leaning more strongly against having it be a default to a usual
template argument since in several important ways it does not behave like one
(e.g., it isn't meaningful in function templates).


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Herb Sutter                 2228 Urwin, Ste 102         voice (416) 618-0184
Connected Object Solutions  Oakville ON Canada L6L 2T2    fax (905) 847-6019





Author: jbuck@synopsys.com (Joe Buck)
Date: 1995/07/13
Raw View
I wrote:
>>Consider the clone operation: we want all objects derived from a
>>particular base class to be able to duplicate themselves.
>>
>>class Clonable
>>{
>>public:
>>  template <class T=current_class> virtual T * clone() const
>>  {
>>     return new T(*this);
>>  }
>>};
>>
>>Now each class derived from Clonable has a proper clone method.
>>
>>Here we see why this is very different from a template: you can safely
>>make a virtual function this way because there's exactly one function
>>in each class, where existing member templates correspond to an indefinite
>>number of functions.

esap@cs.tut.fi (Pulkkinen Esa) writes:
>No. There _could_ be many of the functions in the same class, consider
>a call to the clone method:
>
>Clonable *obj;
>OtherClonable *cloned=obj->template clone<OtherClonable>();

I don't understand what this notation means.  What is OtherClonable?
What is "obj->template clone<OtherClonable>()" ?

The way I was thinking about it, each class derived from Clonable would
have exactly one clone() method and there would be no way to make another:
the current_class style of template would be expanded exactly once for
each class.  If you think it should be some other way, I wish you would
explain it more clearly.

Currently member templates cannot be virtual because this would result
in a potentially infinite virtual function table.  If you want some method
of generating virtual functions for templates, I suspect that clone()
would be one of the most common uses, but you have to assure that it
turns into exactly one function (so the vtable can be built).
--
-- Joe Buck  <jbuck@synopsys.com> (not speaking for Synopsys, Inc)
Anagrams for "information superhighway": Enormous hairy pig with fan
      A rough whimper of insanity





Author: schuenem@informatik.tu-muenchen.de (Ulf Schuenemann)
Date: 1995/07/14
Raw View
There are two discernable ideas we are talking about:
1. A memberfunction that is reinstanciated in each derived class (let's
   call it auto-inst-memfct) like a template is instanciated (once) when
   statically used. Such a memfct can be virtual or static or neither.
2. The usage of current_class in the declaration and implementation
   of memfcts. This can, with the technique of C++compilers, only be
   done, when the implementation of such a memfct is reinstanciated
   in each derived class. Ie. current_class => auto-inst-memfcts.

IMHO it would not be in the spirit of C++ to say that memfct with
current_class must automatically be virtual.

How about a template member declaration without <> meaning
auto-inst-memfcts (BTW: auto-inst would be more powerful by
having also other auto-inst-members like data...):

class B {
  template size_t numinst;
public:
  typedef B  current_class; // workaround for 2.
  template static size_t get_numinst ()
  {     return numinst; }
  template static size_t allinst_sizeof ()
  {     return numinst * sizeof current_class; }
  template virtual size_t dyn_sizeof () const
  {     return sizeof this; }
  template virtual current_class Clone () const
  {     return new this; }
  B ()
  {     numinst++; }
};
template B::size_t numinst = 0;

class D {
public:
  typedef D  current_class; // workaround for 2.
  D ()
  {     numinst++; } // referes to D::numinst
};

But unfortunately 1. drives us into the trap of the anti-inherited-keyword
gang: They will propose us to use a typedef to current_class in each class.
But current_class is needed for nearly every reasonable usage of auto-inst.
So auto-inst and current_class must be instroduced together (or never).

Ulf Schuenemann

--------------------------------------------------------------------
Ulf Sch   nemann
Fakult   t f   r Informatik, Technische Universit   t M   nchen, Germany.
email: schuenem@informatik.tu-muenchen.de





Author: esap@cs.tut.fi (Pulkkinen Esa)
Date: 1995/07/14
Raw View
In article <3u3j9a$1p4@hermes.synopsys.com>,
Joe Buck <jbuck@synopsys.com> wrote:

>I wrote:
>>No. There _could_ be many of the functions in the same class, consider
>>a call to the clone method:
>>
>>Clonable *obj;
>>OtherClonable *cloned=obj->template clone<OtherClonable>();
>
>I don't understand what this notation means.  What is OtherClonable?
>What is "obj->template clone<OtherClonable>()" ?
Maybe I chose the name for the other class wrong.
Well, the clone-function was declared as:

  template <class T=current_class> T* clone() {return new T(this);}

now you might want to use the same function to create objects of other
classes that had the proper constructor. for example, assuming
class X is defined:

class X {
  // ...
  X(const Clonable&);
};

Now to use the clone (member) template to create an X from a clonable
object, you could use:

  Clonable* obj;
  obj = new X;
  X* obj2= obj->template clone<X>();

That is, a member template call [temp.arg.explicit]/2 is
used to call the clone function instantiated with explicit parameter
X, so the call "obj->template clone<X>()" will call the X(const Clonable&)
constructor instead of the copy constructor.

Of course all this kind of calls would be static (since explicit
class name is provided).
--
   Esa Pulkkinen                        | C++ programmers do it virtually
   E-Mail:  esap@cs.tut.fi              | everywhere with a class, resulting
   WWW   :  http://www.cs.tut.fi/~esap/ | in multiple inheritance.






Author: esap@cs.tut.fi (Pulkkinen Esa)
Date: 1995/07/10
Raw View
In article <3trctf$aql@steel.interlog.com>,
Herb Sutter <herbs@interlog.com> wrote:
[ a code example with use of current_class in different translation unit
  with the declaration of the class ]
>Good point, but first let me repeat my intended definition: using
>current_class is an implicitly parameterised type (template) always filled
>with the current most-derived class.  That said, when you write a template
>that uses a parameterised class' member function (e.g., operator++) it must
>be visible to all instantiated/derived classes; i.e., it must be in the
>header, and not in a different xlation unit.

That makes sense.

[ My explanation of how using current_class in different translation
unit from class's declaration leads to difficult parsing problem removed ]

>Aha, no! :-)  If it could be in a different translation unit, that would
>break
>everything... and clearly it has to be in the same translation unit, for
>that's how templates work and to use current_class is to use a template (just
>one that you happen to never need to fill in manually, that's the only
>difference).

If I understand you correctly, current_class is just a strange way
of writing a template _parameter_, which the compiler automatically
fills with the current class's name dynamically by just generating a call
to the right function. Maybe there should
be more verbose indications in the syntax that it's a template, otherwise
people write code using it as if it were a variable (type), and
cause unnecessary code bloat, or problems with instantiation.
My suggestion:

class X
{
  template <class T=current_class> void do_f(void)
  {
    f(dynamic_cast<T*>(this));
  }
};
This would indicate that it's a template more than it is a dynamic
dispatch, maybe even allow using the same template also for static calls.
--
   Esa Pulkkinen                        | C++ programmers do it virtually
   E-Mail:  esap@cs.tut.fi              | everywhere with a class, resulting
   WWW   :  http://www.cs.tut.fi/~esap/ | in multiple inheritance.






Author: herbs@interlog.com (Herb Sutter)
Date: 1995/07/11
Raw View
In article <3trs8e$ru@peippo.cs.tut.fi>, esap@cs.tut.fi (Pulkkinen Esa) wrote:
>
>If I understand you correctly, current_class is just a strange way
>of writing a template _parameter_, which the compiler automatically
>fills with the current class's name dynamically by just generating a call
>to the right function. Maybe there should
>be more verbose indications in the syntax that it's a template, otherwise
>people write code using it as if it were a variable (type), and
>cause unnecessary code bloat, or problems with instantiation.
>My suggestion:
>
>class X
>{
>  template <class T=current_class> void do_f(void)
>  {
>    f(dynamic_cast<T*>(this));
>  }
>};
>This would indicate that it's a template more than it is a dynamic
>dispatch, maybe even allow using the same template also for static calls.

This is a good point, and I think a good alternative.  A few thoughts on the
ramifications of making this an explicit template:

1) It seems to solve the problems some mentioned about "how does the compiler
know" (whether current_class is used).  True, the compiler could still look
through the source which would be in the same xlation unit, but making the
template explicit may make things easier for compiler writers (though perhaps
a little harder in other ways, see next point).

2) The template parm still should not be entered by any client code... if
there are other templated parms, perhaps the one defaulting to current_class
should always be last and never be instantiable directly by the user.  IOW, in
your example the user would always write something like "X::do_f()", never
"X::do_f<??>()".  If there were additional parameters, like:

    template<class A, class T=current_class> void do_f(void) { /*...*/ };

then the user would always write something like "X::do_f<MyClass>()", and
again never be allowed to supply the parameter defaulting to current_class.
This would require changing the default-arg rules slightly to accomodate this
special case; I'm not against that in principle, but I did like the original
(implicit template) idea because it didn't require any changes to existing
rules.

3) That said, sometimes classes themselves (not just member functions) need to
know current_class, and therefore you might have "template<class
T=current_class> class X { /* ...uses current_class info, say to store a
pointer...*/ };".

Overall, it seems to me that both the implicit and explicit forms have
advantages: the implicit form prevents the user from ever supplying the
template parm without requiring the compiler to do extra work to prevent it
(since the template parm is not visible to the user); the explicit form may
make things easier for the compiler by declaring which classes/functions use
current_class information.  I'm still leaning toward the implicit form just
because it doesn't require any existing rules to change, but if it's not as
easy to implement as it appears to a non-compiler writer like me, then
supplying the functionality through a special form of template default parm
should be a workable alternative.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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/11
Raw View
In article <3trn2i$25s@usenet.rpi.edu>,
   vandevod@avs.cs.rpi.edu (David Vandevoorde) wrote
[some of my own quotes elided]:
>
>[ in the following, multiple versions of the regular function f(X) are
>  assumed to exist ]
>
>>  class A {
>>  public:
>>      void do_f()  { f(dynamic_cast<current_class*>(this)); }
>>  };
>
>But if you use "current_class" only outside the class declaration, this
>implicit template character cannot be recognized from the declaration
>alone. This would pretty much rule out repository-based instantiation
>mechanisms (and my understanding of Stroustrup's "Design & Evolution of
>C++" is that this repository approach is more "in the spirit of C++"
>than the manual inclusion of member definitions).

Mmm, now I see where you're coming from.  Good point.  In another article in
this thread, Esa wrote:

>class X
>{
>  template <class T=current_class> void do_f(void)
>  {
>    f(dynamic_cast<T*>(this));
>  }
>};

I've followed it up in another article, but this seems to be a viable
alternative and looks like it would solve the problem you mention, since now
the declaration alone is enough -- i.e., the templating has been made
explicit.

A small concern: this form would require a minor change to existing rules to
prevent users from filling in that (now-visible) template parm.

That concern aside, would such a declaration solve the problems you mentioned?
 I'm not a compiler writer, so I'm relying on those who know more about it to
let me know how implementable any particular solution is.

>However, even _if_ inclusion of definitions along with declarations of
>parameterized classes were mandated, I suspect it would burden the
>compiler significantly because it could never be sure of whether a
>declaration was a true class of a class template until it saw all
>its member definitions... but how would it know that it saw _all_
>thoses definitions when some members could be inherited or over-
>ridden.

Hmm.  What if we made the templating explicit, as above: doesn't the last also
apply to current instantiated/inherited/overridden templates?  So how is it
being resolved now?  I've never seen code that tries to override a template
member function, so I can't say whether it's legal or not; but whatever
solution is in place now should still work, shouldn't it?  This is after all a
template -- one that happens to have a little more compiler support because
the compiler fills it in rather than the user, and the compiler knows to
change pointer types down the hierarchy, but other than that what works for
templates today ought to work for current_class.

>In summary, it is the _implicit_ template character of current_class
>that makes it unviable (IMHO): templates are currently identified as
>through their declaration only (independently of their definition).
>(I think that was also the point of another posting; I didn't read
>it carefully enough):

Thanks again, Daveed.  You're making me more aware of the implementation
issues.  Please let me know whether you think making the template explicit
would solve the problems.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Herb Sutter                 2228 Urwin, Ste 102         voice (416) 618-0184
Connected Object Solutions  Oakville ON Canada L6L 2T2    fax (905) 847-6019





Author: jbuck@synopsys.com (Joe Buck)
Date: 1995/07/11
Raw View
esap@cs.tut.fi (Pulkkinen Esa) writes:
>If I understand you correctly, current_class is just a strange way
>of writing a template _parameter_, which the compiler automatically
>fills with the current class's name dynamically by just generating a call
>to the right function. Maybe there should
>be more verbose indications in the syntax that it's a template, otherwise
>people write code using it as if it were a variable (type), and
>cause unnecessary code bloat, or problems with instantiation.
>My suggestion:

class X
{
  template <class T=current_class> void do_f(void)
  {
    f(dynamic_cast<T*>(this));
  }
};

>This would indicate that it's a template more than it is a dynamic
>dispatch, maybe even allow using the same template also for static calls.

This is a very special kind of template, one which is re-implemented for
every deriving class.  I agree that the template notation is better.  It
seems to me, though, that if you consider it that way, for many uses you
no longer need the dynamic casts: the templates are expanded at compile
time so we have the compile-time type of the objects.  We already have
covariant return types.

Consider the clone operation: we want all objects derived from a
particular base class to be able to duplicate themselves.

class Clonable
{
public:
  template <class T=current_class> virtual T * clone() const
  {
     return new T(*this);
  }
};

Now each class derived from Clonable has a proper clone method.

Here we see why this is very different from a template: you can safely
make a virtual function this way because there's exactly one function
in each class, where existing member templates correspond to an indefinite
number of functions.

While this is interesting, I think it's too late for this round of
standardization.  It might be worth more investigation and
experimentation.


--
-- Joe Buck  <jbuck@synopsys.com> (not speaking for Synopsys, Inc)
Anagrams for "information superhighway": Enormous hairy pig with fan
      A rough whimper of insanity





Author: vandevod@avs.cs.rpi.edu (David Vandevoorde)
Date: 1995/07/11
Raw View
In article <3ttt91$oqu@steel.interlog.com>,
Herb Sutter <herbs@interlog.com> wrote:
>In article <3trn2i$25s@usenet.rpi.edu>,
>   vandevod@avs.cs.rpi.edu (David Vandevoorde) wrote
>[some of my own quotes elided]:
>>
>>[ in the following, multiple versions of the regular function f(X) are
>>  assumed to exist ]
>>
>>>  class A {
>>>  public:
>>>      void do_f()  { f(dynamic_cast<current_class*>(this)); }
>>>  };
[...]
>Mmm, now I see where you're coming from.  Good point.  In another article in
>this thread, Esa wrote:
>
>>class X
>>{
>>  template <class T=current_class> void do_f(void)
>>  {
>>    f(dynamic_cast<T*>(this));
>>  }
>>};
>
>I've followed it up in another article, but this seems to be a viable
>alternative and looks like it would solve the problem you mention, since now
>the declaration alone is enough -- i.e., the templating has been made
>explicit.

... in the declaration (as opposed to the definition).
>
>A small concern: this form would require a minor change to existing rules to
>prevent users from filling in that (now-visible) template parm.

Well, I had the same reflex at first and thus thought the "better
syntax" should be:
 template<this_class> ...
but when I thought it over, I saw no reason to prevent users from
specifying the 'T' in
 template<class T = this_class> ...
BTW, we could avoid the introduction of a new keyword with:
 template<class T = this> ...
>
>That concern aside, would such a declaration solve the problems you mentioned?

Yes. However, it may behave slightly differently from your proposal.
Let's semi-formalize the specifications of the new approach.

 A type-parameter for a class template or a member function
 template can have a default value "this", indicating that the
 type-parameter should be subsituted by the complete class
 for which the template is instantiated.

The grammar ([temp.param]) would be updated with:

 _type-parameter_:
  ...
  class _identifier_ = this
  typename _identifier_ = this

Example:

 template<typename T = this>
 struct singleton {
     static T* instance() const
         { return instance_? instance_: (instance_ = new T); }
 protected:
     singleton() {}
 private:
     static T* instance_;
 };

 struct B1: singleton {
 };

 template<typename T = this>
 struct B2: singleton<T> {
 };

 struct D1: B1 {
 };

 struct D2: B2 {
 };

 f() {
     D2* d2 = D2::instance(); // OK
     D1* d1 = D1::instance(); // Not OK, requires a cast.
 }

Note that D2 is derived from B2<D2> which in turn is derived from
singleton<D2>. D1 on the other hand, is derived from the non-template
class B1 which has a base class singleton<B1>.

No relaxations as to what can be templated should be introduced
(I hope :). In particular, there can still be no virtual member
function templates.
>
>>However, even _if_ inclusion of definitions along with declarations of
>>parameterized classes were mandated, I suspect it would burden the
>>compiler significantly because it could never be sure of whether a
>>declaration was a true class of a class template until it saw all
>>its member definitions... but how would it know that it saw _all_
>>thoses definitions when some members could be inherited or over-
>>ridden.
>
>Hmm.  What if we made the templating explicit, as above: doesn't the last also
>apply to current instantiated/inherited/overridden templates?  So how is it

No, since once the declaration of a class is parsed, it is unambiguous
which member variables and member functions are parameterized and which
are not.

Let me clarify with an example. Assuming the "implicit scheme":

 struct B {
     void f();
 };

 g() {
     B b;
     b.f(); // OK, no problem B is a simple non-template class.
 }

 void B::f() {
     h(static_cast<current_class*>(this));
     // ?? Oh ?? B was a template after all?? Too late... :-P
 }

You could do even dirtier tricks by inheriting from B...

>being resolved now?  I've never seen code that tries to override a template
[...]
>Thanks again, Daveed.  You're making me more aware of the implementation
>issues.  Please let me know whether you think making the template explicit
>would solve the problems.

You're welcome. This thread is a lot more stimulating than many I've
seen in the comp.*.c++ groups.

I think the explicit scheme is workable and worthwile. Of course, to have
it added to the language at this point, there still should be a strong
justification/motivation in terms of usability. I don't have the patterns
book by Vlissides et al.; I'll try to save some cash this week to remedy
that handicap ;-)

>Herb Sutter                 2228 Urwin, Ste 102         voice (416) 618-0184
>Connected Object Solutions  Oakville ON Canada L6L 2T2    fax (905) 847-6019

All the best,

 Daveed





Author: esap@cs.tut.fi (Pulkkinen Esa)
Date: 1995/07/12
Raw View
In article <3ttsia$oqu@steel.interlog.com>,
Herb Sutter <herbs@interlog.com> wrote:

>2) The template parm still should not be entered by any client code... if
>there are other templated parms, perhaps the one defaulting to current_class
>should always be last and never be instantiable directly by the user.  IOW,
>in your example the user would always write something like "X::do_f()", never
>"X::do_f<??>()".  If there were additional parameters, like:
>
>    template<class A, class T=current_class> void do_f(void) { /*...*/ };
>
>then the user would always write something like "X::do_f<MyClass>()", and
>again never be allowed to supply the parameter defaulting to current_class.

I can't see any reason why the template parameter couldn't be provided
by the user (this was pointed out already in other thread),
current_class (clearly?) just can't be used as an explicit template
parameter, only as a default.

>3) That said, sometimes classes themselves (not just member functions)
>need to
>know current_class, and therefore you might have "template<class
>T=current_class> class X { /* ...uses current_class info, say to store a
>pointer...*/ };".

This is a good observation. First application that comes to my mind is
registration of classes through inheritance:
  template <class T=current_class>
  class X
  {
    static Register_server id;
  public:
    static current_class *Create() { return new T; }
    // ...
  };
  template <class T=current_class>
  Register_server X<T>::id( &X::create );

  class Y : public X { };
   // nothing else needed, there is an individual id
   // object in Y also

Now, this is a powerful technique, with proper definition of Register_server,
allows the base class (or code using the base class) to get information
about (all) derived classes, create objects of derived classes they
have never heard of, and impose various constraints to them
(like if you declared a static (data or function) member
but left it undefined except for the base class, all derived classes
,whether directly or indirectly inherited, would have to implement it.).

btw, to respond to the another thread that suggested using 'this'
instead of 'current_class' to prevent inventing a new keyword:
I find 'this' keyword somewhat confusing, since it has traditionally
been used as a pointer, and it already has a meaning as template
default argument. I would think 'virtual' would be better choice,
if inventing a new keyword is such a bad thing.
--
   Esa Pulkkinen                        | C++ programmers do it virtually
   E-Mail:  esap@cs.tut.fi              | everywhere with a class, resulting
   WWW   :  http://www.cs.tut.fi/~esap/ | in multiple inheritance.






Author: esap@cs.tut.fi (Pulkkinen Esa)
Date: 1995/07/12
Raw View
In article <3tuv75$79p@hermes.synopsys.com>,
Joe Buck <jbuck@synopsys.com> wrote:
>
>Consider the clone operation: we want all objects derived from a
>particular base class to be able to duplicate themselves.
>
>class Clonable
>{
>public:
>  template <class T=current_class> virtual T * clone() const
>  {
>     return new T(*this);
>  }
>};
>
>Now each class derived from Clonable has a proper clone method.
>
>Here we see why this is very different from a template: you can safely
>make a virtual function this way because there's exactly one function
>in each class, where existing member templates correspond to an indefinite
>number of functions.

No. There _could_ be many of the functions in the same class, consider
a call to the clone method:

Clonable *obj;
OtherClonable *cloned=obj->template clone<OtherClonable>();

Of course this requires that OtherClonable class has a corresponding
constructor that takes Clonable& as parameter.

I see no reason to disallow such code. BUT, the function can only
be "virtual" in those instances, where the actual template parameter
is the same as the current class's name (the current_class keyword
ensures that) This is why I didn't write the function virtual in
my original example. The current_class-
keyword would have to be enough to inform compiler that the function
actually called is decided run-time, and static calls could be made
by supplying the template argument. (one of the reasons I would think
replacing 'current_class' with 'virtual' might work, but since
the whole discussion so far speaks of current_class, I do too...)
--
   Esa Pulkkinen                        | C++ programmers do it virtually
   E-Mail:  esap@cs.tut.fi              | everywhere with a class, resulting
   WWW   :  http://www.cs.tut.fi/~esap/ | in multiple inheritance.






Author: herbs@interlog.com (Herb Sutter)
Date: 1995/07/09
Raw View
In article <3tn2mm$sq4@usenet.rpi.edu>,
   vandevod@avs.cs.rpi.edu (David Vandevoorde) wrote:
>In article <3tmsck$gnv@steel.interlog.com>,
>Herb Sutter <herbs@interlog.com> wrote:
>>    class Singleton {
>>        static Singleton* Instance() {
>>            if (!_instance)
>>                _instance = new Singleton;
>>            return _instance;
>>        }
>>    private:
>>         static  Singleton* _instance; // omitting for now the issue
>>    };                                 // of how to even manage this
>>
>>    class MySingle : public Singleton {
>>    public:
>>        MyMethod (...);
>>    };  // not quite good enough
>>
>>The main problem is that this solution is not equivalent to writing
>>our  singleton class manually, for now applications can  no  longer
>>call:
>>
>>     MySingle::Instance()->MyMethod();   // error
>
>Do it via a regular function template instead:
>
> template<class C> inline
> C* instance<C>() {
>     return static_cast<C*>(C::Instance());
> }
>
>so your above call becomes:
>
> instance<MySingle>()->MyMethod();

Thanks for the comment.  I've gome through several phases of reactions and
have spent much more time than I originally intended thinking about it.  :-)
Hopefully I've successfully cancelled my earlier (incorrect) followups.
Here's the analysis I ended up with:

This has several problems.  From least to greatest, they are: a) it seems
inelegant because it removes pattern functions from the pattern; b) it is
error-prone since it relies on programmer discipline in the client code; c) it
does not solve the problem since Singleton still needs derived class
information for other reasons (i.e., to declare its _instance pointer with the
correct type).

It also does not solve the other Examples: For instance, we cannot get Example
2   s mainline, but would end up with something like:

  template<class C>
  do_f(C c) { f(c); };

  main() {
    B b;
    do_f<B>(b);  // essentially doing manual polymorphism instead of b.do_f()
                 // also, doesn't protect against do_f<A>(b)
  }

For the commented reasons, this isn   t equivalent to the proposed current_class
solution.  Speaking of Example 2:

>>EXAMPLE 2: MULTIPLE DISPATCH
>[...]
>>In article <DB9CtB.6Er@eunet.ch>,
>>   xar@pax.eunet.ch (Benjamin Rosenbaum) wrote:
>>>Wouldn't it be nice if function overloading were
>>>polymorphic by arguments, so that in...
>>>
>>>  class A {
>>>             void do_f() {f(this);}
>>>           };
>>>  class B: public A {};
>>>
>>>  void f(A &){cout << "this gets called...";};
>>>  void f(B &){cout << "...but wouldn't this be better?"};
>
>Should be "A*" and "B*" I guess.

I meant to leave the original poster's code as-is; but you're right, and I've
corrected it (and the three other errors) in the comment.

>>>
>>>  main ()
>>>  {
>>>  B b;
>>>  b.do_f();
>>>  }
>>>
>>>....f(B &) would get called?

<snip>

>>However, consider:
>>
>>  class A
>>  {
>>  public:
>>      void do_f()  { f(dynamic_cast<current_class*>(this)); }
>>  };
>>
>>Now  this  program  works as desired, with the  rest  of  the  code
>
>And how must a compiler/linker resolve that call?
>I think that for this to work, we would have to add a significant burden
>to compiler writers.

What, specifically?  If we treat current_class as an implicit parameterised
type (template) that is specially supported to be always filled in with the
current type (which the compiler already knows about in all the cases where it
can be used), why won't the existing template rules work?

>I feel C++ often offers alternatives to
>"mixins" which are more orthogonal to the inheritance concept.

Thanks for the comments.  Please elaborate.

> Daveed

Regards,

Herb


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Herb Sutter                 2228 Urwin, Ste 102         voice (416) 618-0184
Connected Object Solutions  Oakville ON Canada L6L 2T2    fax (905) 847-6019





Author: esap@cs.tut.fi (Pulkkinen Esa)
Date: 1995/07/09
Raw View
In article <3toq7e$qb2@steel.interlog.com>,
Herb Sutter <herbs@interlog.com> wrote:
>>>However, consider:
>>>
>>>  class A
>>>  {
>>>  public:
>>>      void do_f()  { f(dynamic_cast<current_class*>(this)); }
>>>  };
[a question about how to implement it removed]
>What, specifically?  If we treat current_class as an implicit parameterised
>type (template) that is specially supported to be always filled in with the
>current type (which the compiler already knows about in all the cases where it

consider: (this is your example with definition of do_f moved to some other
          file).
class X
{
public:
  void do_f();
};

// In some other file:
void X::do_f()
{
  f(dynamic_cast<current_class*>(this));
}

Now, how would you implement this?
 a) make a new virtual function table entry for f() in X and
    call it through it? No, since the virtual function table must
    be known after complete class declaration. Only linker could
    compose virtual function tables, which has repeatedly been
    observed as unaffordable.

 b) make a table of possible functions that can be called when the
    function do_f is defined. Can't, because you can't know what
    classes might derive from X, all such classes would have to be known.

 c) generate new X::do_f() functions for each derived class.
    This would require a new virtual function table entry for
    do_f, otherwise the dynamic_cast would be equal to
    "dynamic_cast<X*>(this)", and the call would still go to
    wrong destination. That is, do_f would have to be virtual.
    But even if it were virtual, only the linker could build the derived
    class's virtual function table, because the compiler doesn't
    know that X::do_f() has used current_class until it has seen
    the definition, which might be in different translation unit from
    all derived classes.
 d) using some extralinguistic magic, change the program as if it were:
    (i.e. I think it can't be done without explicitly declaring somehow
    which functions use current_class.)

   class X
   {
     template <class T> void __do_f_impl();
     virtual void do_f() { this->template __do_f_impl<current_class>(); }
     // this is easier to generate, assuming the definition is
     // in the class declaration.
   };

   // in the translation unit defining do_f:
   template <class T> void X::__do_f_impl<T>()
   {
     f(dynamic_cast<T*>(this));
   }

 e) what other alternatives are there?
[Note followups only to comp.std.c++]
--
   Esa Pulkkinen                        | C++ programmers do it virtually
   E-Mail:  esap@cs.tut.fi              | everywhere with a class, resulting
   WWW   :  http://www.cs.tut.fi/~esap/ | in multiple inheritance.











Author: vandevod@troi.cs.rpi.edu (David Vandevoorde)
Date: 1995/07/09
Raw View
In article <3toq7e$qb2@steel.interlog.com>,
Herb Sutter <herbs@interlog.com> wrote:
>In article <3tn2mm$sq4@usenet.rpi.edu>,
>   vandevod@avs.cs.rpi.edu (David Vandevoorde) wrote:
>>In article <3tmsck$gnv@steel.interlog.com>,
>>Herb Sutter <herbs@interlog.com> wrote:
>>>    class Singleton {
>>>        static Singleton* Instance() {
>>>            if (!_instance)
>>>                _instance = new Singleton;
>>>            return _instance;
>>>        }
>>>    private:
>>>         static  Singleton* _instance; // omitting for now the issue
>>>    };                                 // of how to even manage this
>>>
>>>    class MySingle : public Singleton {
>>>    public:
>>>        MyMethod (...);
>>>    };  // not quite good enough
>>>
>>>The main problem is that this solution is not equivalent to writing
>>>our  singleton class manually, for now applications can  no  longer
>>>call:
>>>
>>>     MySingle::Instance()->MyMethod();   // error
>>
>>Do it via a regular function template instead:
>>
>> template<class C> inline
>> C* instance<C>() {
>>     return static_cast<C*>(C::Instance());
>> }
>>
>>so your above call becomes:
>>
>> instance<MySingle>()->MyMethod();
>
>Thanks for the comment.  I've gome through several phases of reactions and
>have spent much more time than I originally intended thinking about it.  :-)
>Hopefully I've successfully cancelled my earlier (incorrect) followups.
>Here's the analysis I ended up with:
>
>This has several problems.  From least to greatest, they are: a) it seems
>inelegant because it removes pattern functions from the pattern; b) it is
>error-prone since it relies on programmer discipline in the client code; c) it
>does not solve the problem since Singleton still needs derived class
>information for other reasons (i.e., to declare its _instance pointer with the
>correct type).

a) I suppose that's a matter of taste. There is indeed a certain
   "aesthetism" in keeping a whole pattern in a single compact unit
   (in casu: a class), but - as a aluded to in my former comment -
   this may not be a preferred approach in C++. I feel the STL is a
   nice example demonstrating that C++ idioms often benefit from a
   (loose) collaboration between classes and regular functions.
b) Why? If you don't provide a way for the client to instantiate or
   access the singleton other than the instance<C> function that you
   provide, the client will have no choice but to use the pattern
   correctly (or will have compile errors otherwise).
c) Not really. You can keep the "_instance" pointer to he base subobject
   and rely on the safe cast in the instance<C> function.

>
>It also does not solve the other Examples: For instance, we cannot get Example
>2   s mainline, but would end up with something like:

I intended the comments above only for that particular idiom. I admit I
commented on that idiom mostly because I recognized it and have used and
refined it quite a bit in the past.
>
>  template<class C>
>  do_f(C c) { f(c); };
>
>  main() {
>    B b;
>    do_f<B>(b);  // essentially doing manual polymorphism instead of b.do_f()
>                 // also, doesn't protect against do_f<A>(b)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A matter of taste (again :) maybe, but I do not want protection from it
because I feel its a natural case of clipping; in fact, it _explicitly_
requests the clipping (though off hand, I'm not sure it's legal :).
>  }
>
>For the commented reasons, this isn   t equivalent to the proposed current_class
>solution.  Speaking of Example 2:
>
>>>EXAMPLE 2: MULTIPLE DISPATCH
>>[...]
>>>In article <DB9CtB.6Er@eunet.ch>,
>>>   xar@pax.eunet.ch (Benjamin Rosenbaum) wrote:
>>>>Wouldn't it be nice if function overloading were
>>>>polymorphic by arguments, so that in...
>>>>
[ errors purposefully left in for sake of integrity ]
>>>>  class A {
>>>>             void do_f() {f(this);}
>>>>           };
>>>>  class B: public A {};
>>>>
>>>>  void f(A &){cout << "this gets called...";};
>>>>  void f(B &){cout << "...but wouldn't this be better?"};
>>>>
>>>>  main ()
>>>>  {
>>>>  B b;
>>>>  b.do_f();
>>>>  }
>>>>
>>>>....f(B &) would get called?
>
><snip>
>
>>>However, consider:
>>>
>>>  class A
>>>  {
>>>  public:
>>>      void do_f()  { f(dynamic_cast<current_class*>(this)); }
>>>  };
>>>
>>>Now  this  program  works as desired, with the  rest  of  the  code
>>
>>And how must a compiler/linker resolve that call?
>>I think that for this to work, we would have to add a significant burden
>>to compiler writers.
>
>What, specifically?  If we treat current_class as an implicit parameterised
>type (template) that is specially supported to be always filled in with the
>current type (which the compiler already knows about in all the cases where it
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I guess this is where I am a bit confused. How can the compiler know what
"current_class" will be in class A when the derived classes haven't been
compiled (or, for that sake written) yet?
If the inheritance mechanism has to be aware of the dependencies of
certain member functions on "current_class" I fear things may get very
complex. Especially when current_class is only used outside the class
declaration; in that case the inheriting class is totally unaware of
the template_like character in its base.
I suppose I'm missing a point somewhere...?

>can be used), why won't the existing template rules work?
>
>Thanks for the comments.  Please elaborate.

You're welcome. I tried clarifying my thoughts above. My main concerns
are about realizability; I haven't studied you example patterns well
enough to come up with satisfactory (to me :) work-arounds for each of
them (the singleton being an exception).

>Herb Sutter                 2228 Urwin, Ste 102         voice (416) 618-0184
>Connected Object Solutions  Oakville ON Canada L6L 2T2    fax (905) 847-6019

 Daveed





Author: herbs@interlog.com (Herb Sutter)
Date: 1995/07/10
Raw View
In article <3tp6du$qfh@usenet.rpi.edu>,
   vandevod@troi.cs.rpi.edu (David Vandevoorde) wrote:
>>>>    class Singleton {
>>>>        static Singleton* Instance() {
>>>>            if (!_instance)
>>>>                _instance = new Singleton;
>>>>            return _instance;
>>>>        }
>>>>    private:
>>>>         static  Singleton* _instance; // omitting for now the issue
>>>>    };                                 // of how to even manage this
>>>>
>>>>    class MySingle : public Singleton {
>>>>    public:
>>>>        MyMethod (...);
>>>>    };  // not quite good enough
>>>>
>>>>The main problem is that this solution is not equivalent to writing
>>>>our  singleton class manually, for now applications can  no  longer call:
>>>>     MySingle::Instance()->MyMethod();   // error
>>>
>>>Do it via a regular function template instead:
>>> template<class C> inline
>>> C* instance<C>() {
>>>     return static_cast<C*>(C::Instance());
>>> }
>>>so your above call becomes:
>>> instance<MySingle>()->MyMethod();
>>
>>This has several problems.  From least to greatest, they are: a) it seems
>>inelegant because it removes pattern functions from the pattern; b) it is
>>error-prone since it relies on programmer discipline in the client code; c)
>>it does not solve the problem since Singleton still needs derived class
>>information for other reasons (i.e., to declare its _instance pointer with
>>the correct type).
>
>a) I suppose that's a matter of taste. There is indeed a certain
>   "aesthetism" in keeping a whole pattern in a single compact unit
>   (in casu: a class), but - as a aluded to in my former comment -
>   this may not be a preferred approach in C++. I feel the STL is a
>   nice example demonstrating that C++ idioms often benefit from a
>   (loose) collaboration between classes and regular functions.

True.  Specifically what I was getting at was that doing it this way tends to
draw away from the design goal of simply mixing in behaviour a la ": public
Pattern" with no extra work/knowledge required for either the derived-class
programmer or for the client code.

Another point in this line is that, this way, every function requiring
current_class information would have to be split out into its own templated
function.  I can think of simple mixins where every function requires it,
leaving little for the mixin to do.

>b) Why? If you don't provide a way for the client to instantiate or
>   access the singleton other than the instance<C> function that you
>   provide, the client will have no choice but to use the pattern
>   correctly (or will have compile errors otherwise).

In this case, you're quite right (which is why I spent so much time thinking
about your suggestion).  However, I was thinking more of the other examples
(as below) where we will be relying on programmer discipline to "get the class
right", which would be unfortunate.  (You see, in this case, we only need to
pass a class to the function; in Example 2 we need to pass both a class and an
instance.)

>c) Not really. You can keep the "_instance" pointer to he base subobject
>   and rely on the safe cast in the instance<C> function.

Hmm.  True, but... hmm.  Let me think about this one so that I have time to
get over my initial "but that's ugly" reaction. :-,

One quick thought: In the other examples, we have classes storing (non-static)
pointers to their current_class; if we then rely on function templates, we get
back to the "programmer discipline" problem if client code calls one of our
valid functions with a valid class and a valid instance, but the class and
instance don't go together (i.e., dynamic_cast fails; perhaps static_cast
would help alleviate this, but I want to think some more).

At any rate, my initial gut feel is that we're relying on client code too
much, and putting a burden on the client programmer... even if we can arrange
it so that all illegal things are trapped as errors (which I'm not convinced
we can), it seems to me the actual error messages he'll get aren't terribly
enlightening (consider what you get sometimes when using STL the wrong way).
IOW, the client programmer will need to become familiar with our
implementation details to diagnose errors easily... he shouldn't need to do
that.

>>It also does not solve the other Examples: For instance, we cannot get
>>Example 2   s mainline, but would end up with something like:
>
>I intended the comments above only for that particular idiom. I admit I
>commented on that idiom mostly because I recognized it and have used and
>refined it quite a bit in the past.

BTW, don't get me wrong... you're quite right that your suggestion can pretty
much solve Singleton using existing rules.  The unfortunate part is that
Singleton is (as mentioned in the writeup) a very simple example and it took
some thinking for me to prove to myself that the solution doesn't help equally
with the other cases.  I do appreciate your making the point.

>>  template<class C>
>>  do_f(C c) { f(c); };
>>
>>  main() {
>>    B b;
>>    do_f<B>(b); // essentially doing manual polymorphism instead of b.do_f()
>>                // also, doesn't protect against do_f<A>(b)
>                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>A matter of taste (again :) maybe, but I do not want protection from it
>because I feel its a natural case of clipping; in fact, it _explicitly_
>requests the clipping (though off hand, I'm not sure it's legal :).

It should be; with "class B: public A" you can throw a B& into an A& slot.

At any rate, I agree that something you want to slice the object; but if so,
you can always use this kind of design.  My thought was that in the original
we are specifically concerned with matching up types properly and preventing
slicing; we ought to have a way to implement that without relying on the
client's good graces.

>>>>  class A {
>>>>  public:
>>>>      void do_f()  { f(dynamic_cast<current_class*>(this)); }
>>>>  };
>>>
>>>And how must a compiler/linker resolve that call?
>>>I think that for this to work, we would have to add a significant burden
>>>to compiler writers.
>>
>>What, specifically?  If we treat current_class as an implicit parameterised
>>type (template) that is specially supported to be always filled in with the
>>current type (which the compiler already knows about in all the cases where
>               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>I guess this is where I am a bit confused. How can the compiler know what
>"current_class" will be in class A when the derived classes haven't been
>compiled (or, for that sake written) yet?

When compiling class A, it knows it's an A* and doesn't need any other
information.  When it's compiling class B (derived from A) it knows it's a B*
and doesn't need any other information... etc.  This falls out of the fact
that "using current_class" is implicitly parameterising on (templating) a type
which happens to be always filled in by the compiler as the current type.  All
it is is an implicit template with a little automatic support to fill it in
transparently so the derived classes don't have to (since according to the
language rules, as shown, they cannot fill it in properly).

>If the inheritance mechanism has to be aware of the dependencies of
>certain member functions on "current_class" I fear things may get very
>complex. Especially when current_class is only used outside the class
>declaration; in that case the inheriting class is totally unaware of
>the template_like character in its base.
>I suppose I'm missing a point somewhere...?

This doesn't seem much different than a template's using member functions of a
parameterised class, such as an operator++... they are required to be visible
so that the compiler does know about them (and therefore are placed in the
header), and I can't offhand see how this would be different.

Again, these are good comments; but is there any case where the template rules
fail us?  It seems to me that current_class is just an implicit template, and
the only difference is that it gets a little special compiler support for one
feature that the programmer can't easily supply himself: it's always
instantiated as the current class.  Does saying it this way make any more
sense?  I could be missing something, too, but if so I can't quite see what it
is.

Regards,

Herb


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Herb Sutter                 2228 Urwin, Ste 102         voice (416) 618-0184
Connected Object Solutions  Oakville ON Canada L6L 2T2    fax (905) 847-6019





Author: vandevod@avs.cs.rpi.edu (David Vandevoorde)
Date: 1995/07/10
Raw View
[as suggested by another contributor - name escapes me - I put the
 followup field to comp.std.c++; I hope it works ]

In article <3trcdu$aql@steel.interlog.com>,
Herb Sutter <herbs@interlog.com> wrote:
>In article <3tp6du$qfh@usenet.rpi.edu>,
>   vandevod@troi.cs.rpi.edu (David Vandevoorde) wrote:

[ discussion on elegant implementation of singletons elided ]

[ in the following, multiple versions of the regular function f(X) are
  assumed to exist ]

>>>>>  class A {
>>>>>  public:
>>>>>      void do_f()  { f(dynamic_cast<current_class*>(this)); }
>>>>>  };
>>>>
>>>>And how must a compiler/linker resolve that call?
>>>>I think that for this to work, we would have to add a significant burden
>>>>to compiler writers.
>>>
>>>What, specifically?  If we treat current_class as an implicit parameterised
>>>type (template) that is specially supported to be always filled in with the
>>>current type (which the compiler already knows about in all the cases where
>>               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>I guess this is where I am a bit confused. How can the compiler know what
>>"current_class" will be in class A when the derived classes haven't been
>>compiled (or, for that sake written) yet?
>
>When compiling class A, it knows it's an A* and doesn't need any other
>information.  When it's compiling class B (derived from A) it knows it's a B*
>and doesn't need any other information... etc.  This falls out of the fact
>that "using current_class" is implicitly parameterising on (templating) a type

But if you use "current_class" only outside the class declaration, this
implicit template character cannot be recognized from the declaration
alone. This would pretty much rule out repository-based instantiation
mechanisms (and my understanding of Stroustrup's "Design & Evolution of
C++" is that this repository approach is more "in the spirit of C++"
than the manual inclusion of member definitions).

However, even _if_ inclusion of definitions along with declarations of
parameterized classes were mandated, I suspect it would burden the
compiler significantly because it could never be sure of whether a
declaration was a true class of a class template until it saw all
its member definitions... but how would it know that it saw _all_
thoses definitions when some members could be inherited or over-
ridden.

I really the concept is only viable if C++ was equipped with a
"true" module system... but I understand such a radical feature
will not be added to C++ anytime soon.

>which happens to be always filled in by the compiler as the current type.  All
>it is is an implicit template with a little automatic support to fill it in
>transparently so the derived classes don't have to (since according to the
>language rules, as shown, they cannot fill it in properly).
>
[ removed my vaguer previous argument ]
>
>This doesn't seem much different than a template's using member functions of a
>parameterised class, such as an operator++... they are required to be visible
>so that the compiler does know about them (and therefore are placed in the
>header), and I can't offhand see how this would be different.

Actually, the definitions are not required to be in the header according
to the draft submitted for review. Note also that there is a distinction
between a "(standard) header" (which can be seen as a language feature) and
a "header file" which is a purely conventional use of a preprocessor
feature. Unfortunately, many compilers impose the inclusion of template
declarations and definitions into a single translation unit.
>
>Again, these are good comments; but is there any case where the template rules
>fail us?  It seems to me that current_class is just an implicit template, and
>the only difference is that it gets a little special compiler support for one
>feature that the programmer can't easily supply himself: it's always
>instantiated as the current class.  Does saying it this way make any more
>sense?  I could be missing something, too, but if so I can't quite see what it
>is.

In summary, it is the _implicit_ template character of current_class
that makes it unviable (IMHO): templates are currently identified as
through their declaration only (independently of their definition).
(I think that was also the point of another posting; I didn't read
it carefully enough):

>Herb Sutter                 2228 Urwin, Ste 102         voice (416) 618-0184
>Connected Object Solutions  Oakville ON Canada L6L 2T2    fax (905) 847-6019

 Daveed





Author: herbs@interlog.com (Herb Sutter)
Date: 1995/07/10
Raw View
In article <3tpau2$8ne@peippo.cs.tut.fi>,
   esap@cs.tut.fi (Pulkkinen Esa) wrote:
>In article <3toq7e$qb2@steel.interlog.com>,
>Herb Sutter <herbs@interlog.com> wrote:
>>>>However, consider:
>>>>
>>>>  class A
>>>>  {
>>>>  public:
>>>>      void do_f()  { f(dynamic_cast<current_class*>(this)); }
>>>>  };
>[a question about how to implement it removed]
>>What, specifically?  If we treat current_class as an implicit parameterised
>>type (template) that is specially supported to be always filled in with the
>>current type (which the compiler already knows about in all the cases where
>
>consider: (this is your example with definition of do_f moved to some other
>          file).
>class X
>{
>public:
>  void do_f();
>};
>
>// In some other file:
>void X::do_f()
>{
>  f(dynamic_cast<current_class*>(this));
>}
>
>Now, how would you implement this?

Good point, but first let me repeat my intended definition: using
current_class is an implicitly parameterised type (template) always filled
with the current most-derived class.  That said, when you write a template
that uses a parameterised class' member function (e.g., operator++) it must be
visible to all instantiated/derived classes; i.e., it must be in the header,
and not in a different xlation unit.

> c) generate new X::do_f() functions for each derived class.

Exactly, since using current_class is to use an implicit template.

>    This would require a new virtual function table entry for
>    do_f, otherwise the dynamic_cast would be equal to
>    "dynamic_cast<X*>(this)", and the call would still go to
>    wrong destination. That is, do_f would have to be virtual.

Good point.  I had assumed this, but never stated it explicitly: any function
using current_class would be implicitly virtual, or we would require that only
virtual functions may use current_class.

>    But even if it were virtual, only the linker could build the derived
>    class's virtual function table, because the compiler doesn't
>    know that X::do_f() has used current_class until it has seen
>    the definition, which might be in different translation unit from
>    all derived classes.

Aha, no! :-)  If it could be in a different translation unit, that would break
everything... and clearly it has to be in the same translation unit, for
that's how templates work and to use current_class is to use a template (just
one that you happen to never need to fill in manually, that's the only
difference).

>[Note followups only to comp.std.c++]

Yes, good point; I suppose it's beyond the general-interest stage now.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Herb Sutter                 2228 Urwin, Ste 102         voice (416) 618-0184
Connected Object Solutions  Oakville ON Canada L6L 2T2    fax (905) 847-6019





Author: vandevod@avs.cs.rpi.edu (David Vandevoorde)
Date: 1995/07/08
Raw View
In article <3tmsck$gnv@steel.interlog.com>,
Herb Sutter <herbs@interlog.com> wrote:
>This is a copy of the public comment I've submitted regarding the proposed
>"current_class" keyword (a better name than the original "actual_class").
[...]
>EXAMPLE 1: IMPLEMENTING THE SINGLETON PATTERN
>
>The  first example considers implementing a generic version  of  an
>example  from  Design  Patterns: the Singleton  pattern.   It  will
[...]
>Consider  designing  a  class MySingle  that  should  behave  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 Singleton
>    {
>        static Singleton* Instance()
>        {
>            if (!_instance)
>                _instance = new Singleton;
>            return _instance;
>        }
>
>    private:
>         static  Singleton* _instance; // omitting for now the issue
>                                       // of how to even manage this
>    };
>
>    class MySingle : public Singleton
>    {
>    public:
>        MyMethod (...);
>    };  // not quite good enough
>
>The main problem is that this solution is not equivalent to writing
>our  singleton class manually, for now applications can  no  longer
>call:
>
>     MySingle::Instance()->MyMethod();   // error

Do it via a regular function template instead:

 template<class C> inline
 C* instance<C>() {
     return static_cast<C*>(C::Instance());
 }

so your above call becomes:

 instance<MySingle>()->MyMethod();

If you don't like the (first) empty parentheses, you can obtain the same
effect with an "instance" helper class template and an appropriately
overloaded operator-> (may require a little more from the optimizer if
performance is critical).
>
>as  they  should because MySingle::Instance() returns a Singleton*,
>not  a  MySingle*.  This solution requires the application  to  use
>RTTI on the returned pointer:
>
>     (dynamic_cast<MySingle*>MySingle::Instance())->MyMethod()

Why require RTTI when you know the type anyway? (see also above)
>
>which is tedious and error-prone.

Not if you provide a function for it.
[...]
>EXAMPLE 2: MULTIPLE DISPATCH
[...]
>In article <DB9CtB.6Er@eunet.ch>,
>   xar@pax.eunet.ch (Benjamin Rosenbaum) wrote:
>>Wouldn't it be nice if function overloading were
>>polymorphic by arguments, so that in...
>>
>>  class A {
>>             void do_f() {f(this);}
>>           };
>>  class B: public A {};
>>
>>  void f(A &){cout << "this gets called...";};
>>  void f(B &){cout << "...but wouldn't this be better?"};

Should be "A*" and "B*" I guess.
>>
>>  main ()
>>  {
>>  B b;
>>  b.do_f();
>>  }
>>
>>....f(B &) would get called?
      ^^^^^^^^^^^^^^^^^^^^^^^^
Personally, I would find that very confusing.
>
>Again  the template workaround could be applied, but again for  the
>same  reasons deriving more than one level deep would  fail  (i.e.,
>the  workaround  would  work for this example,  but  fails  in  the
>general  case,  for  example if we had  a  class  C  :  public  B).
>However, consider:
>
>  class A
>  {
>  public:
>      void do_f()  { f(dynamic_cast<current_class*>(this)); }
>  };
>
>Now  this  program  works as desired, with the  rest  of  the  code

And how must a compiler/linker resolve that call?
I think that for this to work, we would have to add a significant burden
to compiler writers.
[...]
>SUMMARY
>
>For  the  price  of  a single keyword (one that  consistently  uses

Certainly, a "keyword" is only part of the "price to pay". One of the
many other aspects that matter is the translation complexity. If I
understand the proposed requirements well (which may very well not be
the case), this additional complexity would be considerable.
[...]
>such  as  the ProtectedObject in Example 4.  Partial (and  fragile)
>workarounds  exist that work in some cases, but they fail  even  in
>normal use, forcing us to choose between mixins and polymorphism.
[...]
Although that can be true, I feel C++ often offers alternatives to
"mixins" which are more orthogonal to the inheritance concept.

>Herb Sutter                 2228 Urwin, Ste 102         voice (416) 618-0184
>Connected Object Solutions  Oakville ON Canada L6L 2T2    fax (905) 847-6019

 Daveed






Author: herbs@interlog.com (Herb Sutter)
Date: 1995/07/08
Raw View
This is a copy of the public comment I've submitted regarding the proposed
"current_class" keyword (a better name than the original "actual_class").
I've left comp.object in the distribution list because the original
discussion was also repeated there, and because the contents affect
techniques for writing generic OO patterns.

Thanks again to all who participated in the "Proposal for Writing Generic
Patterns" thread, which proposed the new keyword.  Your comments have made
this a more well-rounded proposal, particularly in demonstrating examples
requiring this new functionality.

Although this proposal has already been submitted, I'd be interested in
additional comments since I intend to continue supporting this proposal
through the standards process as I am able.

Herb


===================================================================

                      Draft Standard Comment:

               The Case For a current_class Keyword



       Submitted by: Herb Sutter, Connected Object Solutions

                    email: herbs@interlog.com

                       Friday, July 7, 1995

        2228 Urwin, Suite 102, Oakville ON Canada, L6L 2T2
           Tel.: (416) 618-0184     Fax: (905) 847-6019

===================================================================



-------------------------------------------------------------------
ABSTRACT


Allowing  base classes to know the exact type of the current  most-
derived class in which they are being used is a great advantage  at
low cost, because it is both:

   a) essential for writing entire classes of mixin designs,
      particularly generic patterns; and

   b) implementable with one keyword without impacting the existing
      language rules.

I  will  describe  the  motivation  for  a  proposed  current_class
keyword,  whose  equivalent functionality already exists  in  other
languages  (e.g., Eiffel's like current, Sather's  SAME).   I  will
then demonstrate current_class's usefulness by implementing several
mixin/pattern designs from current literature (e.g., Gamma et al.'s
"Design  Patterns"),  showing, through failed workaround  attempts,
that  the  same  results  cannot be obtained without  current_class
information.

To address the questions in Section 6.4.1 of "Design and Evolution"
in  a  nutshell:  The proposed change will be shown  to  be  widely
applicable  (the  entire  industry is  getting  into  patterns  and
generic  patterns now), general-purpose (applicable  to  more  than
just   pattern  mixins,  see  Example  4),  implementable  on   all
reasonable  hardware  and systems, essential  for  certain  pattern
mixin   programming   styles,  specifically  beneficial   for   the
design/implementation/use of libraries, free of side  effects,  and
not  preventing  any existing programming styles  or  breaking  any
existing  programs.   The  proposed  change  does  not  affect  the
efficiency  of  code that does not use it, acts  as  a  specialised
compiler-supported template (and adds a vtable) to classes which do
use  it,  requires no recompilation of existing programs, and  does
not  affect external linkage.  The change is a single keyword which
has  already  proven  easy to grasp in Usenet discussions,  and  is
unlikely to lead to demands for further extensions because it is  a
simple self-contained concept.



-------------------------------------------------------------------
SUGGESTED FEATURE: DESCRIPTION


To implement transparent pattern mixins, we need a mechanism for  a
base class to know the type of (though not being able to declare  a
member variable of) the current derived class.  I propose that this
take the form of an current_class keyword.  For example, consider:

  class A {
       current_class* Function() { return
  dynamic_cast<current_class*>(this); };
  };

  class B : public A {...};   // a B's Function() returns a B*

  class C : public B {...};   // a C's Function() returns a C*

This   example  illustrates  three  main  advantages  that  I  will
illustrate further:

   a) current_class allows generic reuse of a function (e.g.,
      A::Function()) in derived classes without requiring redundant
      redefinitions to supply correct current types;

   b) together with the existing dynamic_cast, it allows a base class
      to know and use the true this pointer for the current object
      (via dynamic_cast<current_class*>(this));

   c) it also allows further polymorphic dispatch of a base member
      function's return value (e.g., the result of Function()).

The  next  four examples will illustrate that this is not  possible
with  current  methods, despite attempts at workarounds  using  the
"class D : public B<D>" idiom, which fails in each case.  What will
be   illustrated  is  that,  in  essence,  using  current_class  is
implicitly  parameterising on a type (in this case, that  parameter
is  always filled in with the current class), and therefore current
template  rules  continue to work properly  and  as  expected  when
applied to classes invoking current_class.



-------------------------------------------------------------------
EXAMPLE 1: IMPLEMENTING THE SINGLETON PATTERN


The  first example considers implementing a generic version  of  an
example  from  Design  Patterns: the Singleton  pattern.   It  will
illustrate   the  key  points,  including  current   (and   failed)
workaround attempts.  (Because this pattern is so simple, some have
questioned  why  one would put such a simple design  into  its  own
generic pattern; but this example is for illustration and the  same
issues arise with patterns supplying more complex behaviour.)

Consider  designing  a  class MySingle  that  should  behave  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  the  pattern member variable and  function  for  every
class we want to have behave as a Singleton, which prevents generic
reuse.   Instead, we would like to generalise the Singleton pattern
into  a  class  or  template  that we  can  just  inherit  from  or
instantiate, like:

    class MySingle : public Singleton    // if only we could do this!
    {
    public:
        MyMethod (...);
    };  // complete definition, equivalent in every way to the above

The problem is that we can't write such a generic Singleton pattern
under  the  draft standard.  A naive attempt would be to  duplicate
the core Singleton in its own class (identically to the above):

    class Singleton
    {
        static Singleton* Instance()
        {
            if (!_instance)
                _instance = new Singleton;
            return _instance;
        }

    private:
         static  Singleton* _instance; // omitting for now the issue
                                       // of how to even manage this
    };

    class MySingle : public Singleton
    {
    public:
        MyMethod (...);
    };  // not quite good enough

The main problem is that this solution is not equivalent to writing
our  singleton class manually, for now applications can  no  longer
call:

     MySingle::Instance()->MyMethod();   // error

as  they  should because MySingle::Instance() returns a Singleton*,
not  a  MySingle*.  This solution requires the application  to  use
RTTI on the returned pointer:

     (dynamic_cast<MySingle*>MySingle::Instance())->MyMethod()

which is tedious and error-prone.  Or, alternatively we could foist
off   the   work   onto   the   MySingle   programmer   by   making
Singleton::Instance() pure virtual, forcing (and relying on) him to
override it in MySingle and all its derivatives; yet even then  the
function  will  be identical in every class except for  its  return
type  and  it  is  wasteful (and dangerous) to  try  to  force  the
programmer  to repeat it even with a macro.  And, even  if  it  was
workable,   it  would  still  not  address  the  issue  of   proper
transparent reuse.

The next obvious question is, What if we used templates?

    template <class T>
    class Singleton
    {
        static T* Instance()
        {
            if (!_instance)
                _instance = new T;
            return _instance;
        }

    private:
        static T* _instance;
    };

    template<class T>
    T* Singleton<T>::_instance = 0;

Can  we  derive what we want?  Yes, as long as we always inherit
directly from the mixin:

    class MySingle : public Singleton<MySingle>
    {
    public:
        MyMethod (...);
    };  // better, but must derive from Singleton<> directly

This works properly as long as we don't try to inherit further from
MySingle,  in which case it fails miserably because further-derived
classes  will  have  as  their  ancestor  Singleton<MySingle>,  not
Singleton<WhatIReallyAm>.  In general, consider:

  template<class T> class Pattern { /*...uses actual type T...*/ };

  class FirstClass : public Pattern<FirstClass> { /*...so far so good...*/ };

  class OtherClass : public FirstClass { /*...oops...*/ };

With  a  Pattern implemented as above to imitate the  current_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  current_class information).  To fix this, you need to  resort
to a parallel class hierarchy like:

    Pattern        FirstClassProto
     |  \         /      |
     |   \       /       |
     |  FirstClass  OtherClassProto
      \            /
       \          /
        OtherClass

The fatal problem here is not that this workaround doubles the size
of  the  class hierarchy or even that it's error-prone;  the  fatal
problem  is  that it destroys polymorphism between  FirstClass  and
OtherClass  and so forces a very inelegant tradeoff: We may  either
have  polymorphism or mix in generic patterns, but we  may  not  do
both.    This  restriction  seems  unreasonable,  especially   when
current_class solves the whole problem simply and elegantly:

    class Singleton
    {
        static current_class* Instance()
        {
            if (!_instance)
                _instance = new current_class;
            return _instance;
        }

    private:
        static current_class* _instance;
    };

    current_class* Singleton::_instance = 0;   // see below

Now we can go ahead and cleanly mix in our generic pattern:

    class MySingle : public Singleton
    public:
        MyMethod (...);
    };  // ...and we're done, cleanly and elegantly.

Now,  getting  back to that static variable: Can we  deal  with  it
easily?   Yes,  simply by remembering that the use of current_class
can be viewed as an implicit type parameterisation; in other words,
as  a  specially supported implicit template.  Since  clearly  each
class  should have its own static _instance member (since the  type
will  differ),  each class should indeed get  its  own  copy.   For
example:

  class B { public: static current_class* _p; /*...*/ };
  current_class* B:_p = 0;
  /* generates B* B::_p = 0; */

  class D1 : public B { /*...*/ };
  /* transparently generates D1* D1::_p = 0; as would a template */

  class D2 : public D1 { /*...*/ };
  /* transparently generates D2* D2::_p = 0; as would a template */



-------------------------------------------------------------------
EXAMPLE 2: MULTIPLE DISPATCH


Here is an actual recent Usenet question that can be satisfied only
with  current_class  information, and it  illustrates  another  key
advantage:

In article <DB9CtB.6Er@eunet.ch>,
   xar@pax.eunet.ch (Benjamin Rosenbaum) wrote:
>Wouldn't it be nice if function overloading were
>polymorphic by arguments, so that in...
>
>  class A {
>             void do_f() {f(this);}
>           };
>  class B: public A {};
>
>  void f(A &){cout << "this gets called...";};
>  void f(B &){cout << "...but wouldn't this be better?"};
>
>  main ()
>  {
>  B b;
>  b.do_f();
>  }
>
>....f(B &) would get called?

Again  the template workaround could be applied, but again for  the
same  reasons deriving more than one level deep would  fail  (i.e.,
the  workaround  would  work for this example,  but  fails  in  the
general  case,  for  example if we had  a  class  C  :  public  B).
However, consider:

  class A
  {
  public:
      void do_f()  { f(dynamic_cast<current_class*>(this)); }
  };

Now  this  program  works as desired, with the  rest  of  the  code
unchanged.   This  demonstrates  that  the  current_class  facility
allows  not  only  easy multiple dispatch, but  in  general  allows
proper  polymorphism  on  the return  type  of  a  mixed-in  member
function, which is a very powerful tool in many situations.

In the same article came the following example:



-------------------------------------------------------------------
EXAMPLE 3: IMPLEMENTING THE VISITOR PATTERN


  >I want to implement the Visitor pattern from
  >Gamma et.al.'s Design Patterns, as shown below
  >(it's for double-dispatch-in-C++.) Without the
  >macro, you have to make sure to type the same
  >damn thing in every subclass of A, since
  >the only thing we want to vary is the scope
  >of "this"! Is there any way to do it with
  >templates?  Even better, is there a way to really
  >make sure it gets done in every subclass of A?
  >(I guess it could be pure virtual in A).

  <example using macro to redefine accept() member function in
  every subclass elided>

Using the template workaround and the parallel-hierarchy structure,
we  get  (the  following  is a modified  version  of  the  poster's
original code):

  class Visitor
  {
  public:
    void visit (A &) {cout << "Visited A" << endl;}
    void visit (B &) {cout << "Visited B" << endl;}
  };

  template<class T>
  class Visitee
  {
  public:
    virtual void accept (Visitor &v) {
  v.visit(dynamic_cast<T&>(*this)); };
  };

  class A_impl {};
  class A : public A_impl, public Visitee<A> {};

  class B_impl : public A_impl {};  // keep polymorphism in ?_impl classes
                                    // for whatever that's worth
  class B: public B_impl, public Visitee<B> {};

  main()
  {
   A a;
   B b;
   Visitor v;
   a.accept(v);  // should call v.visit(A&)
   b.accept(v);  // should call v.visit(B&)
  }

Again,  the problem is that to get mixins we are forced to give  up
polymorphism (here between A and B).  But with current_class we can
define a proper Visitee mixin that works properly in all cases:

  class Visitee
  {
  public:
    virtual void accept (Visitor &v)
      { v.visit(dynamic_cast<current_class&>(*this)); };
  };

  class A: public Visitee {};
  class B: public A {};  // inherits the mixin naturally, can't be done today
                      // note, no dual class hierarchy, simple/elegant design

This  single  change  eliminates the  need  for  the  double  class
hierarchy,  simplifies the design, and allows not only  polymorphic
multiple  dispatch  but  also the writing  of  an  easily  reusable
generic pattern.



-------------------------------------------------------------------
EXAMPLE 4: A ProtectedObject MIXIN


Consider  a  mixin  class, called ProtectedObject,  which  supplies
behaviour  for storing a checksum of an object's physical  bits  so
that  the  object  can  detect  unauthorised  modifications  (e.g.,
through rogue pointers elsewhere in the program, or through cosmic-
ray  strikes in software controlling a comm satellite,  etc.).   To
protect  an object, we would like to simply include ProtectedObject
in its class' inheritance list to mix in the behaviour; then all we
should need to do is call the generic SetCheck function at the  end
of  each  of our own functions that can change the internal  state,
and  call the generic Check() function at the start of each of  our
own functions to ensure no tampering has taken place.

This  cannot  be  done in a generic base class without  letting  it
somehow:  a)  get the correct this pointer for the current  object;
and  b)  determine  the  size  of the object.   With  current_class
information, we can create such a generic mixin:


  class ProtectedObject
  {
  public:
      bool Check()    { return (_check == CalcCheck()); };
      void SetCheck() { _check = CalcCheck(); };

  protected:
      int  CalcCheck()
      { /* calculate and return a checksum based on bytes in memory from
           dynamic_cast<current_class*>(this) up to
           dynamic_cast<current_class*>(this) + sizeof(current_class) - 1,
           correcting for the checksum's own value as needed */
      };

      int  _check;
  };

This kind of mixin is not possible under the current draft for  the
same  reasons  as in the other examples: Derived class  information
cannot  be  brought  into the base class without  using  a  special
template   as   a   workaround,  which  workaround  itself   breaks
polymorphism (among other drawbacks).



-------------------------------------------------------------------
QUESTIONS & ANSWERS


Q1 (from Usenet):
>I guess this is inspired by Eiffel's "like current" feature?

A1:   No, as I don't know Eiffel, though I guess this means I'm not
the first to see this need.  Matt Kennell mentioned the same thing,
and  that  similar functionality exists in Sather -- clearly, then,
this seems to be a useful construct to have if it is indeed already
present in other well-known OO languages.


Q2 (from Usenet):
>Should the following be type-correct?
>
>    class A {
>        current_class* Function() { return new A; };
>    };

A2:   No,  for  the  new  keyword doesn't  change  existing  rules.
Specifically,  since  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 current class  (therefore  the  above
definition, while legal, would simply prevent derivation  from  A).
Again,    remember   that   using   current_class   is   implicitly
parameterising  on  a type, and therefore the template  and  typing
rules still work fine.


Q3:   Can  I declare a member variable of type current_class?   For
example:

  class Pattern
  {
  private:
      current_class myVariable;  // can cause size problems if allowed
  };

A3:   No.   I propose that this should be illegal, because:  a)  it
would  mean  the base class portion would actually change  size  in
each derived class, wreaking havoc with existing rules; and b) if a
class does need to create/use an instance of current_class, it  can
already do so (by storing a pointer to it and allocating it on  the
heap,  as  does  Singleton in Example 1  above).   In  short,  base
classes may use and store pointers or references to objects of type
current_class,  but  may not store member  variables  of  the  type
itself.



-------------------------------------------------------------------
SUMMARY


For  the  price  of  a single keyword (one that  consistently  uses
existing  template and other rules), we gain an enormous  advantage
in  writing reusable code: full generic patterns.  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  the ProtectedObject in Example 4.  Partial (and  fragile)
workarounds  exist that work in some cases, but they fail  even  in
normal use, forcing us to choose between mixins and polymorphism.

Please  consider this proposal.  I am personally convinced  of  its
merits -- indeed, of its necessity -- and I hope I have been able to
clearly present some of the reasons why this is a simple, powerful,
and  essential language feature for a popular and growing style  of
generic programming.


Regards,  and thanks for all the hard work you've all  already  put
into this standard on our behalf,


Herb Sutter
herbs@interlog.com

Connected Object Solutions
2228 Urwin, Suite 102   Oakville ON Canada   L6L 2T2
Tel.: (416) 618-0184   Fax: (905) 847-6019


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Herb Sutter                 2228 Urwin, Ste 102         voice (416) 618-0184
Connected Object Solutions  Oakville ON Canada L6L 2T2    fax (905) 847-6019