Topic: static virtual: Submitted Public Comment


Author: schuenem@informatik.tu-muenchen.de (Ulf Schuenemann)
Date: 1995/07/19
Raw View

In article <3tnq3j$mrs@ixnews4.ix.netcom.com>, donorgan@ix.netcom.com (Don Organ) writes:
|> However, I think there are 2 problems:
|> Problem1: As Eric pointed out, implementations normally pass the this
|> pointer to nonstatic member functions. Nothing on line 15-18 provides
|> the implementation with the knowledge whether it should pass the this
|> pointer. Eric suggested a syntax to resolve this (my interpretation,
|> possibly wrong)
|> 15 int (B::*psvf)() static = &B::svf;
|> This provides the information needed. Does the following work any
|> better?
|> 15 int (static B::*psvf)() = &B::svf;


As far as I can remember an article (in CUJ, I think) memfctptr for
virtual memfct are implemented using a stubfunction, that works like
a compiletime bound memfct that makes a virtual call.

 struct X {
  virtual void memfct ();  // has a this

  // introduced by compiler:
  void nv__memfct()  // nonvirtual memfct
  { memfct(); } // virtual call
 };
 void (X::*vmfp)() = &X::memfct;
 // is transformed to:
 void (X::*vmfp)() = &X::nv__memfct;

This prevents a distinction between memfctptrs with virtual and
nonvirtual binding.
One can use the same pattern to implement memfctptr to virtual static
with few effort:

 struct Y {
  virtual static void stmemfct ();// has no this
      // ptrtype: void(*)()

  // introduced by compiler:
  void nv__stmemfct()  // nonvirtual memfct (has a this)
      // ptrtype: void(Y::*)()
  { stmemfct(); } // virtual static call
 };

This leaves us problem #2:
In article <3tnq3j$mrs@ixnews4.ix.netcom.com>, donorgan@ix.netcom.com (Don Organ) writes:
[..]
|>  1 struct B { static virtual svf(); virtual vf(); f(); };
|>  2 struct D : public B { static virtual svf(); virtual vf(); f(); };
|>    ...
|>  3 int (*psf)() = &B::svf;    // Treat as static (ignore the virtual)
[..]
|> 15 int (B::*psvf)() = &B::svf; // a virtual (that is also static)
[..]
|> Problem2: The rvalue &B::svf appears twice in this example, on
|> line 3 and line 15. On line 3, the left side of the
|> assignment needs an lvalue of type "pointer to function" (etc.).
|> On line 15, the left side of the assignment needs an lvalue of type
|> "pointer to member function" (etc.).
|> As a user, I could easily live with some type of implicit conversion
|> for either line 3 or line 15. But, I'm not a language lawyer or a
|> compiler writer.

[ Here again, I see a parallelity to nonstatic memfct. How can I distinguish
between virtual and nonvirtual memfctptrs?

 struct XX : X {
  virtual void memfct ();
 };
 X *xx = new XX;
 void (X::* vmfp)() = &X::memfct;
 (xx->*vmfp)();  // calls XX::memfct
 void (X::*nvmfp)() = &nonvirtual X::memfct;
 (xx->*nvmfp)();  // calls X::memfct

 struct YY : Y {
  virtual static void stmemfct ();
 };
 Y *yy = new YY;
 void (Y::* vsmfp)() = &Y::stmemfct;
 (yy->*vsmfp)();  // calls YY::stmemfct
 void (*nvsmfp)() = &nonvirtual Y::stmemfct;
 (*nvsmfp)();  // calls Y::stmemfct

Yes, nonvirtual memfctptrs to virtual nonstatic memfcts are not very usefull
and might be bad style. So we can focus on virtual static. ]

The distinction memfctptr or fctptr should be made at the point of
'taking the address'. How about the implicit '&' of nonmemberfunctions
to denote the nonvirtual case?

 void foo() {}
 // the expression
 //  foo  is of type void(*)()
 //  Y::stmemfct is of type void(*)()
 //  &Y::stmemfct is of type void(Y::*)()
 void (Y::* vsmfp)() = &Y::stmemfct;
 void (*nvsmfp)() =  Y::stmemfct;


Ulf Schuenemann

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





Author: donorgan@ix.netcom.com (Don Organ)
Date: 1995/07/08
Raw View
In <MATT.95Jul7153301@godzilla.EECS.Berkeley.EDU>
matt@godzilla.EECS.Berkeley.EDU writes:
>
>In article <3tih38$nsm@ixnews5.ix.netcom.com> donorgan@ix.netcom.com
(Don Organ) writes:
>
>> > [c] Does it fit with the rest of the language?
>>
>> Yes - C++ has done a good job of preventing coupling between
>> orthogonal features. I view "static" and "virtual" as orthogonal.
>> See Example 3 above, as well as the 1st "aside".
>
>I don't think this is true: static and virtual aren't at all
>orthogonal.  A static member function is a member function that
>belongs to a class as a whole rather than to any particular object.  A
>virtual member function is a function where the actual function called
>at runtime depends on the class of the object through which it is
>called.  You can't have a function that's both of these.
>

True, I can't have a function that is both virtual and static. The
draft (and all C++ compilers I'm aware of) doesn't allow it. But
it does make sense - there is no contradiction.
Here's a modified Example 2 (not 3 - my typo above) from the my
posting (I've added line numbers, lines not in the original posting
are marked with a letter):

 // Example 2
 // Illegal in draft. This is what I want.
1 struct B { static virtual void f1(); virtual void f2(); };
2 struct D : public B { static void f1(); void f2(); };
3 void X(B*p) { p->f1(); p->f2(); }
4 main() {
5  B *p = new B;
6  X(p); // X() calls B::f1() and  B::f2()
7  p = new D;
8  X(p); // X() SHOULD call D::f1() and D::f2()
8a          B::f1();            // no object required
8b          D::f1();            // no object required
8c          p -> B::f1();       // same as B::f1()
8d          p -> D::f1();       // same as D::f1()
8e          p -> B::f2();
8f          p -> D::f2();
9 }

On line 3, the two virtual member functions (f1 and f2)and resolve
to the dynamic type of p*. This makes logical sense for both the
static and the nonstatic member function. The functions
called are shown in the comments on lines 6 and 8: the static and
non-static virtual function resolve in the same manner when called
using class member access syntax ("->" here).
Not apparent in this example is that f1() is not passed a this
pointer (since it is static), but f2() is passed a this pointer
(as are all nonstatic member functions). That is the significance
of static versus non-static.
Line 8a and 8b call the static member functions without an object, as
static member functions are often called.  The "virtual"ness of B::f1()
and D::f1() is not relevant here. This is consistent with the behavior
for line 8e and 8f: the "virtual"ness of B::f2() and D::f2() is not
relevant there.

I believe the above example shows that static virtual member functions
do make sense and are consistent with the rest of the language (namely
static nonvirtual member functions and nonstatic virtual member
functions). If there is an inconsistency or something is
ambiguous I'd appreciate seeing that in an example or described
in more precisely then your offering.

[snip]

Don Organ






Author: JdeBP@jba.co.uk (Jonathan de Boyne Pollard)
Date: 1995/07/08
Raw View
matt@godzilla.EECS.Berkeley.EDU wrote:
: In article <3tih38$nsm@ixnews5.ix.netcom.com> donorgan@ix.netcom.com (Don Organ) writes:
: > > [c] Does it fit with the rest of the language?
: >
: > Yes - C++ has done a good job of preventing coupling between
: > orthogonal features. I view "static" and "virtual" as orthogonal.
: > See Example 3 above, as well as the 1st "aside".

: I don't think this is true: static and virtual aren't at all
: orthogonal.  A static member function is a member function that
: belongs to a class as a whole rather than to any particular object.  A
: virtual member function is a function where the actual function called
: at runtime depends on the class of the object through which it is
: called.  You can't have a function that's both of these.

I used to agree with this point of view, but having worked with C++
implementations where classes are themselves first-class objects I now
disagree, and find myself wavering towards supporting the static virtual
proposal.

A static function member isn't a function that belongs to a class, since to
make things regular that would require that it were passed an invisible
`this_class' pointer to the "object" for the class in the same way that
function members that belong to class instances are passed a `this' pointer
to the object for the instance.

I don't think that we should be introducing the concept of "class-level"
anything into C++ unless we are prepared to bite the bullet and specify
classes to be first-class objects in their own right.

I support the far simpler case:  A static function member is a function member
that belongs to an instance THAT DOESN'T HAVE A `this' POINTER.  No more; no
less.  This, I suspect, is far closer to the view that most people have of
static function members in C++ than that of "class-level functions".

This is in line with the syntax that allows *all* members (static or
non-static) of a class to be accessed via the `.' operator.  The
classname::function syntax I believe should be regarded as simply a syntactic
bonus that allows such function members to be called without reference to a
particular instance, and should not be regarded as the *primary* means of
accessing static function members.  (A contentious viewpoint, I know, but
at least it is consistent with the C++ ethos that only class instances are
first-class objects.).

Bearing this in mind, it can be seen that whether a function member is
supplied a `this' pointer is entirely unaffected by whether the function is
virtual or not.  It seems perfectly logical to allow virtual function
members that are not passed a `this' pointer as it is to allow non-virtual
function members that are not passed a `this' pointer.

Whether it is useful or not is a different matter.  Just about everything
that people claim requires static virtual methods is just as easy if you
allow classes to be first class objects and implement the class function
members that would otherwise be static virtual as ordinary virtual function
members of the metaclass instead.





Author: ebiederm@cse.unl.edu (Eric Biederman)
Date: 1995/07/08
Raw View
matt@godzilla.EECS.Berkeley.EDU writes:

>In article <3tih38$nsm@ixnews5.ix.netcom.com> donorgan@ix.netcom.com (Don Organ) writes:

>> > [c] Does it fit with the rest of the language?
>>
>> Yes - C++ has done a good job of preventing coupling between
>> orthogonal features. I view "static" and "virtual" as orthogonal.
>> See Example 3 above, as well as the 1st "aside".

>I don't think this is true: static and virtual aren't at all
>orthogonal.  A static member function is a member function that
>belongs to a class as a whole rather than to any particular object.  A
>virtual member function is a function where the actual function called
>at runtime depends on the class of the object through which it is
>called.  You can't have a function that's both of these.

>What people really want, I think, isn't a static virtual function
>(since that doesn't make sense) but rather two functions of the same
>name, one of which is static and one of which is virtual, where the
>compiler automatically generates both functions given a single
>definition.  In some cases, like taking the address, you really have
>to think of them as two separate functions.

No actually it's a virtual class function.
And static functions are simply class functions.

If virtual functions are though of as functions pieced together
with a piece for each type this does make sense.  No if you call it
with respect to any class of course you know which piece to call
but if you call it with respect to some object whose class you're
really not sure of this makes even more sense.

Having too forms of addresses is also consistent with class _data_ members
which have both a class member pointer, and a regular pointer types that
can be applied to them.

>So let's think about this as an overloading question.  Some types of
>overloading (like overloading on return type) are forbidden because
>it's not always possible to tell from context which function should be
>called, while other types (like overloading on number of arguments) is
>allowed.  Which category does overloading on static fall into?  Are
>there any potential ambiguities?

How to declare a virtual static member function pointer, maybe.

>This really isn't such a big deal, anyway.  I have occasionally wanted
>"static virtual" functions.  I couldn't have a static and a virtual
>member function with the same names, so I just used two different
>names.  That's not a major inconvenience.

No but it is is an inconvenience that can be fixed.
Why, not and save every one some heart burn.
>--
>Matt Austern          matt@physics.berkeley.edu
>http://dogbert.lbl.gov/~matt





Author: donorgan@ix.netcom.com (Don Organ)
Date: 1995/07/09
Raw View
In <3tk7aa$f2@crcnis3.unl.edu> ebiederm@cse.unl.edu (Eric Biederman)
writes:
>
>donorgan@ix.netcom.com (Don Organ) writes:
>
[snip]

>>With these changes, the rest of the draft adequately describes the
>>intended behavior. Specificially, these need no changes:
>> 5.2.2 [expr.call] paragraphs 1,2
>> 5.2.4 [expr.ref] 2,6
>> 5.3.1 [expr.unary.op] 2
>> 7.1.1 [dcl.stc] 4
>> 7.1.2 [dcl.fct.spe] all (as amended)
>> 8.3 [dcl.meaning] 1
>> 9.2 [class.mem] 10
>> 9.5 [class.static] all (as amended)
>> 10.2 [class.member.lookup] 5
>> 10.3 [class.virtual] all (as amended)
>> 10.4 [class.abstract] all
>> 11.6 [class.access.virt] all
>> 12.1 [class.ctor] 4
>> 12.6.2 [class.base.init] 7
>> 12.7 [class.cdtor] 3
>> 12.8 [class.copy] 6
>> 13.1 [over.load] 2
>
>I'm not sure of the section probably 5.2.4 [expr.ref] this needs to be
>looked up, but there is one more point to be made clear, there are
>two kinds of pointers to a static virtual function that are needed.
>A normal function pointer, and a virtual static pointer.  The later
>can only be a result of the &class::static_function syntax.  While
>a normal function pointer can result from &class::static_function
>and from &object::static_function.
>
>The type of a static virtual method pointer would resemble
>return_type (class::* )(args...) static
>The keyword static is needed to tell the implementation, essentially
>not to pass the this pointer.
>
>The type of the pointer returned is as always determined by the type
>of the receiving pointer.  Depending on how this is stated in the
draft
>this may need some changes in wording as well.
>
>Also one must not forget assignment of this new pointer type to other
>types, and fill the various levels of undefined, implementation
dependent,
>etc. for casts, to/from other member pointer types, and to/from other
>static pointer types with different arguments.  The base class etc.
>is another issue.
>
>Do you think you could ammend your public comment with regard to
pointers.
>You leave a whole in the language until you handle static virtual
function
>member pointers.  Also the pointer aspects
>(falls in the generalization category) may be almost be more useful.
>This removes one more place where pointers member in the struct become
>no more.  (The old way of doing virtual functions :+] )
>These are particularly nice as you can read them as well.
>
>Sorry I'm short on time to polish this reply as I should so:
>Sincerly,
>Eric Biederman
>ebiederm@cse.unl.edu
>

Thanks for the critical eye. You are right, my submitted comment
didn't address the relationship of static virtual and pointers
to members. (This was also pointed out to me earlier, but I overlooked
this when preparing the comment.)

For the record, I think the relevant sections are:
    3.9.2 [basic.compound] paragraphs 3 and 5
    4.11 [conv.mem]
    5.5 [expr.mptr.oper]
    8.3.3 [dcl.mptr] paragraph 3
and probably
    5.3.1 [expr.unary.op] paragraph 2, 4
    13.4 [over.over] paragraph 3

I've been playing around with this, trying to see what might be
consistent with the April Draft and what conflicts arise.

// Attempting to define natural syntax for pointer to static virtual
// member functions. Illegal in the April Draft.
// THIS IS NOT A PROPOSAL!
 1 struct B { static virtual svf(); virtual vf(); f(); };
 2 struct D : public B { static virtual svf(); virtual vf(); f(); };
   ...
 3 int (*psf)() = &B::svf;    // Treat as static (ignore the virtual)
 4 int i = (*psf)();          // calls B::svf
 5 B *b_ptr = new B;
 6 D *d_ptr = new D;
 7 int (B::*pvf)() = &B::vf; // pointer to member function (virtual)
 8 int (B::*pf)() = &B::f;   // pointer to member function (nonvirtual)
 9 i = (b_ptr ->* pvf)();      // Calls B::vf
10 i = (b_ptr ->* pf)();       // Calls B::f
11 i = (d_ptr ->* pvf)();      // Calls D::vf (since pvf points to a
12                            // virtual member)
13 i = (d_ptr ->* pf)();       // Calls B::f (non-virtual)
14 // Ok so far, Now try static and virtual together
15 int (B::*psvf)() = &B::svf; // a virtual (that is also static)
16                                // (similar to line 7)
17 i = (b_ptr ->* psvf)();     // Call B::svf (similar to line 9)
18 i = (d_ptr ->* psvf)();     // Call D::svf (similar to line 11)

My first response to the above is that pointers to static virtual
members could work in a manner consistent with how pointers to statics
work in the April Draft (as pointers to functions) as well
as how pointers to (virtual) member functions work in the April Draft.
However, I think there are 2 problems:
Problem1: As Eric pointed out, implementations normally pass the this
pointer to nonstatic member functions. Nothing on line 15-18 provides
the implementation with the knowledge whether it should pass the this
pointer. Eric suggested a syntax to resolve this (my interpretation,
possibly wrong)
15 int (B::*psvf)() static = &B::svf;
This provides the information needed. Does the following work any
better?
15 int (static B::*psvf)() = &B::svf;

Problem2: The rvalue &B::svf appears twice in this example, on
line 3 and line 15. On line 3, the left side of the
assignment needs an lvalue of type "pointer to function" (etc.).
On line 15, the left side of the assignment needs an lvalue of type
"pointer to member function" (etc.).
As a user, I could easily live with some type of implicit conversion
for either line 3 or line 15. But, I'm not a language lawyer or a
compiler writer.

Any constructive suggestions? Any other holes?

Don Organ






Author: linhd@bnr.ca (Linh Dang)
Date: 1995/07/09
Raw View
example:

class foo()
{
 public:
  void static_bar();
  void virtual_bar();
};


foo* p;

p->static_bar();


IMHO, we should ban the above syntax for static function call.
It doesn't make any sense to call a class method using an object.

 foo::static_bar();

is THE WAY to invoque a static function.
Ppls will then asks "What's wrong with my design ?" instead of
"Why doens't C++ allow static virtual ?".

------------------
L.D.





Author: schuenem@informatik.tu-muenchen.de (Ulf Schuenemann)
Date: 1995/07/10
Raw View
In article <MATT.95Jul7153301@godzilla.EECS.Berkeley.EDU>, matt@godzilla.EECS.Berkeley.EDU writes:
|> In article <3tih38$nsm@ixnews5.ix.netcom.com> donorgan@ix.netcom.com (Don Organ) writes:
|> > Yes - C++ has done a good job of preventing coupling between
|> > orthogonal features. I view "static" and "virtual" as orthogonal.
|> > See Example 3 above, as well as the 1st "aside".
|>
|> I don't think this is true: static and virtual aren't at all
|> orthogonal.  A static member function is a member function that
|> belongs to a class as a whole rather than to any particular object. A
   ^^^^^^^^^^^^^^^^^^
|> virtual member function is a function where the actual function called
                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^
|> at runtime depends on the class of the object through which it is
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |||||||||||||||||||
|> called.  You can't have a function that's both of these.
   ||||||

I see the properties of `belonging' and binding perfectly orthognal
(when a function is called `through' an object O, as you said):

(a) The function `belongs' to a class vs. `belongs' to an object.
    [ Although one might argue what `belongs' exactly means. That's
      why the standard uses the term `nonstatic/static member' ]

(b) The actual function called at runtime
    depends on the runtime-class of the object O vs.
    depends on the compiletime-class of the object O.


Ulf Schuenemann

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





Author: donorgan@ix.netcom.com (Don Organ)
Date: 1995/07/07
Raw View
I apologize to the modem users for such a large posting.

Here's the formal "public comment" I submitted on the 5th
regarding static virtual member functions (complete with typos).
This is a follow-up to earlier postings I made to this newsgroup.

I was surprised by the amount of traffic this generated. I appreciate
the efforts of all who participated. I feel my "comment" is much better
(clearer, more accurate) then it could have been without observing
this discussion. I had originally suggested that 3 aspects of
static virtuals be considered: 1) static virtual member functions,
2)#1 with the "most derived" static virtual member function callable
from a base-class's constructor and 3) static virtual data.
Based primarily on the newsgroup discussions, I limited my comment
to #1 only, which might have been the least discussed of the three.
(I believe #2 has implementation problems and #3 seems
too contraversial - these are discussed briefly in my comment.)
I think the interesting portion is the "narrative rationale"
(I think most people will want to skip the "changes to the April
Draft").

A reminder that the public comment period is still open (unfortunately,
I don't have the date in front of me now - I think it varies
with country also). I should add that preparing this comment took
much more time than I expected (and probably could have used more).

Thanks again for the help. Flame lightly.

Don Organ


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


As a formal "public comment" there is one aspect of the language I'd
like
to be reconsidered: static virtual member functions.

I feel that the draft's prohibition against static virtual member
functions
is unnecessary and counter-productive, and suggest that the prohibition
should be removed.
Below is:
 formal description of the suggested changes to the draft
 a narrative rationale
 my response to D&E's "Criteria" (although I don't consider this
  an "extension")
 interest extracted from comp.std.c++

Although this static virtual issue is minor compared to the many other
issues you must address, I hope you will give it the serious
consideration
it deserves. If I can be of any assistence, please don't hesitate to
contact me.



Formal Description of the suggested changes to the April draft
-----------------------------------------------------------------------
------
Intention: remove the prohibition of "static virtual" member functions.

7.1.2 [dcl.fct.spec]: change 4th paragraph to:
"The virtual specifier shall be used only in declarations of class
member
functions within a class declaration; se 10.3"
(remove the word 'nonstatic': was "... in declarations of nonstatic
member
functions ...")

9.4.1 [class.mfct.nonstatic]: Note that this section is about nonstatic
member functions. Since the 2nd paragraph already also covers static,
I'm adding virtual static as well. Perhaps these both should be moved
to 9.5. I haven't drafted the language for this move, but would be
happy
to do so. Anyways, here's the changes to the 1st paragraph:
"A nonstatic member function *(begin new language)*, or a static
virtual member function *(end new language)* may be called for an
object
of its class type, or for an object of a class derived (10) from its
class
type, using the class member access syntax (5.2.4, 13.3.1.1). A
*(remove 'nonstatic')* member function may also be called directly
using the function call syntax(5.2.2, 13.3.1.1)
- from within the body of a member function of its class or of a class
derived from its class, or
- from a mem-initializer (12.6.2) for a constructor for its class or
for
a class derived from its class."
(changes indicated inline)



9.4.1 [class.mfct.nonstatic]: 2nd paragraph change to:
"When an id-expression (5.1) that is not part of a class member access
syntax (5.2.4) and not used to form a pointer to member (5.3.1) is
used in the body of a nonstatic member function of class X or used in
the mem-initializer for a constructor of class X, if name lookup (3.4)
resolves the name in the id-expression to a nonstatic nontype member
of class X or of a base class of X, *(begin new language)* or a
virtual static member of class X or of a base class of X, *(end new
language)*
the id-expression is transformed into a class member access expression
(5.2.4) using (*this) (9.4.2) as the postfix-expression to the
left of the . operator.  The member name then refers to the member of
thee
object for which the function is called. Similarly during name lookup,
when an unqualified-id (5.1) used in the definition of a member
function
for class X resolves to a static *(begin new language)* non-virtual
*(end new language)* member, an enumerator or a nested type of X or of
a base class of X, the unqualified-id is transformed into a
qualified-id
(5.1) in which the nested-name-specifier names the class
of the member function. [Example: ..."

9.4.1 [class.mfct.nonstatic]: paragraph 5 (again, since this section
is about nonstatic member functions, I'm not sure this change is
appropriate): change to "A member function may be declared virtual
(10.3)
or pure virtual (10.4)."
(Removed the word 'nonstatic': was "A nonstatic member function ...")


9.5.1 [class.static.mfct]: Change the 2nd paragraph to read:
"[Note: a static member function does not have a this pointer (9.4.2).
] There
shall not be a static and a nonstatic member function with the same
name and
the same parameter types (13.1). A static member function shall not be
declared const, volatile, or const volatile."
(Removed the sentence "A static member function shall not be virtual.")

10.3 [class.virtual]: change the 7th paragraph to read:
"[Note: the virtual specifier implies membership, so a virtual function
cannot be a nonmember (7.1.2) function. A virtual function declared in
one
class can be declared a friend in another class.]"
(Removed the sentence "Nor can a virtual function be a static member,
since a virtual function relies on a specific object for determining
which function to invoke.")

12.5 [class.fre]: change 10th paragraph to:
"Member allocation and deallocation functions cannot be virtual.
However,
the deallocation function actually called is determined by the
destructor
actually called, so if the destructor is virtual the effect is the
same. [Example: ..."
(First sentence was "Since member allocation and deallocation functions
are static they cannot be virtual.")

?? 5.2.4 [expr.ref] I'm unsure about 4th paragraph:
2nd bullet (with E1.E2 syntax where E2 is a static member function)
says that E1.E2 is an lvalue.
4th bullet (same syntax where E2 is a non-static member function)
says the E1.E2 is NOT an lvalue.
(It seems to me they should both be NOT an lvalue - I don't understand
the reason or significance of it being an lvalue in #2, so I don't
understand whether a change is needed here for virtual static.)

?? 10.3 [class.virtual] I'm unsure about the 6th paragraph - it doesn't
seem entirely accurate for static virtuals, but this inaccuracy is
removed by 10.3 paragraph 12. (I think this is equally true
for nonstatic virtuals.)

With these changes, the rest of the draft adequately describes the
intended behavior. Specificially, these need no changes:
 5.2.2 [expr.call] paragraphs 1,2
 5.2.4 [expr.ref] 2,6
 5.3.1 [expr.unary.op] 2
 7.1.1 [dcl.stc] 4
 7.1.2 [dcl.fct.spe] all (as amended)
 8.3 [dcl.meaning] 1
 9.2 [class.mem] 10
 9.5 [class.static] all (as amended)
 10.2 [class.member.lookup] 5
 10.3 [class.virtual] all (as amended)
 10.4 [class.abstract] all
 11.6 [class.access.virt] all
 12.1 [class.ctor] 4
 12.6.2 [class.base.init] 7
 12.7 [class.cdtor] 3
 12.8 [class.copy] 6
 13.1 [over.load] 2

Narrative Rationale
-----------------------------------------------------------------------
------
Please note that I'm not a naive newbie as I'm sometimes assumed to be
when
I memtion this topic. I've a computer engineering degree, 15 years
in software including 7 years intensive in C++ as a technical lead
on a 1M LOC project. (That shows I'm not a newbie - but it doesn't
show that I'm not naive!)

I view this not as an extension, but rather as a simplification.
It is probably the only change request you've received that leaves the
draft smaller and adds capability to the language.

I could find no clear justification for the prohibition in the ARM, D&E
or the April Draft. I infered the thinking was along the lines of
"virtual functions require an object, static member functions are not
associated with an object, therefore these are mutually exclusive".

However, static member functions may be called on an object using
class member access syntax (. or ->), in which case the static type
(as opposed to dynamic type) is used.
For example:

 // Example 1
 struct B { static void f(); /* ... */ };
 void X(B*p) { p->f(); /* same as B::f(); */ }

I interpret this as performing an operation on the class of the object
pointed to by p. I believe it is logical to assume that this call
could also be virtually dispatched. For example:

 // Example 2
 // Illegal in draft. This is what I want.
 struct B { static virtual void f1(); virtual void f2(); };
 struct D : public B { static void f1(); void f2(); };
 void X(B*p) { p->f1(); p->f2(); }
 main() {
  B *p = new B;
  X(p); // X() calls B::f1() and  B::f2()
  p = new D;
  X(p); // X() SHOULD call D::f1() and D::f2()
 }

The symmetry should be apparent. So, I believe this is natural and
consistent.
(And I believe that should be sufficient basis for allowing virtual
static.)

But why would anybody want to use virtual static?
If wanted them (tried to use them) on several occaisions:
 object factories (most recently)
 per class registries with polymorphic behavior
 help & documentation features (class specific in a class
hierarchy)
 built in test/debug capabilities
 problems that RTTI now solves
Specific other uses (suggested by Ulf Schuenemann) include:
DynamicSizeof(),
MemMoveable(), MemCopyable(), and NumInstances().
(Also, adding virtual behavior to the class operator delete [class.fre
-
section 12.5] might have been less creative if static virtuals were
legal at that time. Have there been other creative work-arounds to the
lack of static virtual?))


There is an obvious work around, but I consider it unreliable on large
projects: instead of a single static virtual function,
implement the static function and also a virtual function (of a
slightly
different name) that calls the static function. I'm not concerned about
the extra function call as much as 1) explaining this work-around to
new programmers is hard. They always say "huh?". and 2) the
hard-to-find
bug when someone calls the static function where they should have
called
the virtual function (note: we have times where we also want
to use the class::function() syntax - so we don't make the static
function
private - even if we made it private, we could make the same mistake
from a member function). An example:

 // Example 3
 // Work-around (with a bug)
 struct B {
  static void f();
  virtual void Vf() { f(); };
 };
 struct D : public B {
  static void f();
  virtual void Vf() { f(); };
 };
 void X(B *p) {  // p* might be B or D
  B::f(); // OK
  D::f(); // OK
  p -> Vf();  // OK
  p -> f();  // Hard-to-find programmer error:
     // WRONG if p* is a D!
     // B::f() is called, we
     // wanted D::f()
 }

INFORMALLY, here's a Truth Table that indicates when a static virtual
would have "virtual" behavior:
    Calling syntax:
  B::f()  p->f() or r.f()  f()
Called from: ================================================
Outside of class| 1   2  3
static memfct | 1   2  4
nonstatic memfct| 1   2  5
where B::f() is a static virtual, and B *p, B r&.
1: unambiguous - same as static non-virtual.
2: dispatch virtually through the object (similarly to a nonstatic
virtual)
3: ill-formed, class is not known.
4: same as static non-virtual (call f() for the class of the memfct)
5: dispatch virtually through (*this) (same as nonstatic virtual)
Again, this is natural and consistent with existing aspects of C++.


A couple of asides:
1) I heartily endorsed the concept of const member functions when they
"appeared" (although several of my programmers objected - too
confining,
too much hassle or "false" protection). It both forced the developers
to
think more up-front about their code design and it allowed the compiler
to assist maintenance programmers from making "intent" mistakes by
preventing them from changing data they shouldn't (bugs which were
difficult to find). As a const member function can't "change" the
object, I view a static member function as not being able to even
"examine" the object (i.e. there is no object). However, developers
needing "virtual" capability short-circuit this by making what should
be static member functions nonstatic (see "Design Patterns" -
Gamma et. al page 115 for an example). Thus, there is less protection
against maintenance programmers using data they shouldn't. Having
static virtual would allow us to make a clean distinction as to
when/why to use static member functions.

2) I remember the first time I heard of an inline virtual
function. I thought that made no sense since inline is inherently a
compile-time (early) binding and virtual implied a run-time (late)
binding. I had to play with it a bit to understand the value.
I think static virtual is similar. At first it doesn't make sense
(virtual requires an object, static doesn't have an object).
But if viewed as allowing late binding (through an object) to the
appropriate static member function, it does make sense.




D&E "Criteria"
-----------------------------------------------------------------------
------

> [1] Is it precise? (Can we understand what you are suggesting?) Make
>  a clear, precise statement of the change as it affects the
current
>  draft of the language reference standard.

>From the above, I trust you'll understand what I'm suggesting.
I can't be certain that I didn't miss any neccessary changes in the
draft.

> [a] What changes to the grammar are needed?

Identified above.

> [b] What changes to the description of the language semantics are
needed?

Identified above.

> [c] Does it fit with the rest of the language?

Yes - C++ has done a good job of preventing coupling between
orthogonal features. I view "static" and "virtual" as orthogonal.
See Example 3 above, as well as the 1st "aside".

> [2] What is the rationale for the extension? (Why do you want it, and
why
>  would we also want it?)

> [a] Why is the extension needed?

(Not an extension - we're taking a restriction out. I like
"simplification".)
See above. Basically, I view it as useful. I view the
present prohibition as un-necessary.

> [b] Who is the audience for the change?

There is limited direct support for this change (see "From
comp.std.c++",
below).
However, this is a general purpose change. Possibly useful to a
significant
minority of programmers who currently use both virtual functions and
static functions.
Useful to programmers who segregate "class methods" from "instance
methods"
and are looking for polymorphic "class methods" (thus, I see
wide-spread
OO potential - but this hasn't materalized during discussions on the
net).



> [c] Is this a general-purpose change?

Yes!

> [d] Does it affect one group of C++ language users more than others?

Unsure. (I believe the usefullness of virtual static is more common on
larger designs where more effort may be spent on isolating class from
object behavior. But this is an unsupportable opinion.)

> [e] Is it implementable on all reasonable hardware and systems?

Yes.

> [f] Is it useful on all reasonable hardware and systems?

Yes.

> [g] What kinds of programming and design styles does it support?

Factory methods.  Object - oriented: supports polymorphic behavior on
classes (not just on objects).

> [h] What kinds of programming and design styles does it prevent?

No changes from the Draft without this change.

> [i] What other languages (if any) provide such features?

I have not used any that do. I understand the ObjectPascal (Delphi)
supports this.

> [j] Does it ease the design, implementation, or use of libraries?

Unsure.

> [3] Has it been implemented? (If so, has it been implemented in the
exact
>  form that you are suggesting; and if not, why can you assume that
>  experience from "similar" implementations or other languages will
>  carry over to the features as proposed?)

No (not to my knowledge.)

> [a] What effect does it have on a C++ implementation?

> [i] on compiler organization?

Not sure (expect minimal effect).

> [ii] on run-time support?

Not sure (expect no effect).

> [b] Was the implementation complete?

Not implemented.

> [c] Was the implementation used by anyone other than the
implementer(s)?

N/A

> [4] What difference does the feature have on code?

> [a] What does the code look like without the change?

See Example 3 above. Typically the code has 2 similar member
functions - one is virtual, the other is static. The virtual simply
calls
the static.

> [b] What is the effect of not doing the change?

I'll whimper about C++ growing without polishing the details. (But I'll
get over it.) Also, I'll have to give an occaisional explanation to
maintenance programmers on why I didn't code it more simply.

> [c] Does use of the new feature lead to demands for new support
tools?

No.

> [5] What impact does the change have on efficiency and compatibility
with
 C and existing C++?

No impacts on efficiency or compatibility!

> [a] How does the change affect run-time efficiency?

> [i] of the code uses the new feature?

No worse then a non-member virtual function.

> [ii] of code that does not use the feature?

No change.

> [b] How does the change affect compile and link times?

Negligible.

> [c] Does the change affect existing programs?

> [i] Must C++ code that does not use the feature be recompiled?

No.

> [ii] Does the change affect linkage to languages such as C and
Fortran?

No.

> [d] Does the change affect the degree of static or dynamic checking
> possible for C++ programs?

No.

> [6] How easy is the change to document and teach?

> [a] to novices?

Trivial -  people assume they can do virtual static until they try it.
It's harder to teach them about the Draft as it is today.

> [b] to experts?

I believe it is difficult to teach a C++ expert anything. ;-)

> [7] What reasons could there be for not making the extension? There
will
>  be counter-arguments and part of our job is to find and evaluate
>  them, so you can just as well save time be presenting a
discussion.

I know of no technical reason nor language usability or consistency
reason
why this "extension" should be made. I did use comp.std.c++ to attempt
to find such reasons.
Most counter arguments I've heard are naive - they assume a
contradiction
between virtual (requires an object) and static (no object).

There has also been the argument that it is "too late in the game" for
this change. I'm assuming that is untrue (for relatively minor issues
such as this), otherwise this "public comment" period would be an
insincere gesture.

> [a] Does it affect old code that does not use the construct?

No

> [b] Is it hard to learn?

No

> [c] Does it lead to demands for further extensions?

Of course!
Discussion of static virtual generally leads to 2 related topics:
1) ability for a base constructor to call a more derived
static virtual member function and
2) static virtual data members (and possibly even nonstatic virtual
data members).

I now think these should NOT be standardized now. Although #1 makes
sense from a programmer's perspective, it is not compatible with the
way (I believe) many implementations manage the vtable during execution
of base constructors.  Thus, there would be significant added
implementation complexity unwarrented by the current demand for this
feature.

#2 also makes sense from a programmer's perspective (and possibly also
from an implementer's). There have been convincing arguments that
static
virtual data members could readily implemented into a class's
vtable (assuming that implementation) and that most other issues, such
as name resolution, etc. have already been worked out for virtual and
static members. However, I've seen no attempt to identify the
relevant sections of the draft. There are also (possibly naive)
concerns
that this change might also have unforeseen semantic issues - and
therefore
is probably too risky to standardize at this time.

> [d] Does it lead to larger compilers?

Not sure. But certainly not significantly larger. (Might be smaller -
they
have 1 less error message!)

> [e] Does it require extensive run-time support?

None.

> [8] Are there

> [a] Alternative ways of providing a feature to serve the need?

Other then the hokey double function approach at the user level
(Example 3), I'm not aware of any reasonable alternative.

> [b] Alternative ways of using the syntax suggested?

Not applicable.

> [c] Attractive generalizations of the suggested scheme?

This is a generalization.






>From comp.std.c++
-----------------------------------------------------------------------
------
In an attempt to determine the merit of the static virtual concept, and
to determine if there was any support, I've used comp.std.c++ as
a forum to explore this issue.
Over the past few weeks there have been about 25 postings regarding
static virtual, by about 15 different posters. Threads diverged along
a number of tangents.

Regarding a posting I made requesting specific input for
this "public comment" I received 10 replies (9 e-mail, 1 posting that
wasn't e-mailed). Responses originated from 4 countries, and
judging from the e-mail addresses, 9 companies or sites.
I requested opinions on
 1) static virtual member functions:
  8 in favor, 2 opposed (note, 1 response was in-favor
  of this as a pre-requesite for #2, I'm not sure if his
  support is independent of #2)
 2) also allowing the base constructor to call the most derived
  static virtual function:
  5 in favor, 4 opposed, 1 undecided
 3) also supporting static virtual data members:
  2 in favor (1 strongly, 1 weakly), 6 opposed, 2 uncertain
  or unstated)
(the counts exclude my postion which is now for #1 only).
The period of this very unscientific survey was June 29 through July 4
(a relatively short period considering holidays and vacations).








Author: ebiederm@cse.unl.edu (Eric Biederman)
Date: 1995/07/07
Raw View
donorgan@ix.netcom.com (Don Organ) writes:

>I apologize to the modem users for such a large posting.

>Here's the formal "public comment" I submitted on the 5th
>regarding static virtual member functions (complete with typos).
>This is a follow-up to earlier postings I made to this newsgroup.

Here are my comments to your comments, I've snipped a lot.
[snip]

>12.5 [class.fre]: change 10th paragraph to:
>"Member allocation and deallocation functions cannot be virtual.
>However,
>the deallocation function actually called is determined by the
>destructor
>actually called, so if the destructor is virtual the effect is the
>same. [Example: ..."
>(First sentence was "Since member allocation and deallocation functions
>are static they cannot be virtual.")

More clearly here the memory allocation function in general cannot be
virtual because it is called before the class is constructed and therefore
there is no object to `virtually' resolve which function to call.

I think the wording here really needs a little more consideration
but what I have said begins to point out the basic problem.  Having
a restriction with no good reason is a pain.  That I believe is the point
of this thread/public comment.  Although it may be better to wait until
later to consider this change, after _experience_.

[snip]

>With these changes, the rest of the draft adequately describes the
>intended behavior. Specificially, these need no changes:
> 5.2.2 [expr.call] paragraphs 1,2
> 5.2.4 [expr.ref] 2,6
> 5.3.1 [expr.unary.op] 2
> 7.1.1 [dcl.stc] 4
> 7.1.2 [dcl.fct.spe] all (as amended)
> 8.3 [dcl.meaning] 1
> 9.2 [class.mem] 10
> 9.5 [class.static] all (as amended)
> 10.2 [class.member.lookup] 5
> 10.3 [class.virtual] all (as amended)
> 10.4 [class.abstract] all
> 11.6 [class.access.virt] all
> 12.1 [class.ctor] 4
> 12.6.2 [class.base.init] 7
> 12.7 [class.cdtor] 3
> 12.8 [class.copy] 6
> 13.1 [over.load] 2

I'm not sure of the section probably 5.2.4 [expr.ref] this needs to be
looked up, but there is one more point to be made clear, there are
two kinds of pointers to a static virtual function that are needed.
A normal function pointer, and a virtual static pointer.  The later
can only be a result of the &class::static_function syntax.  While
a normal function pointer can result from &class::static_function
and from &object::static_function.

The type of a static virtual method pointer would resemble
return_type (class::* )(args...) static
The keyword static is needed to tell the implementation, essentially
not to pass the this pointer.

The type of the pointer returned is as always determined by the type
of the receiving pointer.  Depending on how this is stated in the draft
this may need some changes in wording as well.

Also one must not forget assignment of this new pointer type to other
types, and fill the various levels of undefined, implementation dependent,
etc. for casts, to/from other member pointer types, and to/from other
static pointer types with different arguments.  The base class etc.
is another issue.

Do you think you could ammend your public comment with regard to pointers.
You leave a whole in the language until you handle static virtual function
member pointers.  Also the pointer aspects
(falls in the generalization category) may be almost be more useful.
This removes one more place where pointers member in the struct become
no more.  (The old way of doing virtual functions :+] )
These are particularly nice as you can read them as well.

Sorry I'm short on time to polish this reply as I should so:
Sincerly,
Eric Biederman
ebiederm@cse.unl.edu

Hope this _really_ helps.

>Narrative Rationale
>-----------------------------------------------------------------------
>------
>Please note that I'm not a naive newbie as I'm sometimes assumed to be
>when
>I memtion this topic. I've a computer engineering degree, 15 years
>in software including 7 years intensive in C++ as a technical lead
>on a 1M LOC project. (That shows I'm not a newbie - but it doesn't
>show that I'm not naive!)

>I view this not as an extension, but rather as a simplification.
>It is probably the only change request you've received that leaves the
>draft smaller and adds capability to the language.

>I could find no clear justification for the prohibition in the ARM, D&E
>or the April Draft. I infered the thinking was along the lines of
>"virtual functions require an object, static member functions are not
>associated with an object, therefore these are mutually exclusive".

>However, static member functions may be called on an object using
>class member access syntax (. or ->), in which case the static type
>(as opposed to dynamic type) is used.
>For example:

> // Example 1
> struct B { static void f(); /* ... */ };
> void X(B*p) { p->f(); /* same as B::f(); */ }

>I interpret this as performing an operation on the class of the object
>pointed to by p. I believe it is logical to assume that this call
>could also be virtually dispatched. For example:

> // Example 2
> // Illegal in draft. This is what I want.
> struct B { static virtual void f1(); virtual void f2(); };
> struct D : public B { static void f1(); void f2(); };
> void X(B*p) { p->f1(); p->f2(); }
> main() {
>  B *p = new B;
>  X(p); // X() calls B::f1() and  B::f2()
>  p = new D;
>  X(p); // X() SHOULD call D::f1() and D::f2()
> }

>The symmetry should be apparent. So, I believe this is natural and
>consistent.
>(And I believe that should be sufficient basis for allowing virtual
>static.)

>But why would anybody want to use virtual static?
>If wanted them (tried to use them) on several occaisions:
> object factories (most recently)
> per class registries with polymorphic behavior
> help & documentation features (class specific in a class
>hierarchy)
> built in test/debug capabilities
> problems that RTTI now solves
>Specific other uses (suggested by Ulf Schuenemann) include:
>DynamicSizeof(),
>MemMoveable(), MemCopyable(), and NumInstances().
>(Also, adding virtual behavior to the class operator delete [class.fre
>-
>section 12.5] might have been less creative if static virtuals were
>legal at that time. Have there been other creative work-arounds to the
>lack of static virtual?))

This is personal observation only.   One of the difficulties in C++ is in
creating and dealing with persistent objects.  The greatest difficulty
lies in moving these things around in a class independent manner.
Either moving them in memory or the real kicker moving them to disk, and
back again.  When coupled with free store management this can become quite
complex.  The solution many other languages use (this is heresay) is to
let the garbage collection know all about the _actual_ type of an object.

In C++ we have RTTI and virtual methods to finds the _acutal_ type of an
object, and call by reference copy constructors to update virtual function
tables for our objects.  But this does not give the user _complete_
information, or all of the _pertinent_ information to do things with.

As static virtual in this `persistent object' muddle you bet there have
been other creative work arounds.  (sorry waxing philosophical)

The work around is only obvious if you realize what you want is a static
virtual function.  It is difficult to do that.

>There is an obvious work around, but I consider it unreliable on large
>projects: instead of a single static virtual function,
>implement the static function and also a virtual function (of a
>slightly
>different name) that calls the static function. I'm not concerned about
>the extra function call as much as 1) explaining this work-around to
>new programmers is hard. They always say "huh?". and 2) the
>hard-to-find
>bug when someone calls the static function where they should have
>called
>the virtual function (note: we have times where we also want
>to use the class::function() syntax - so we don't make the static
>function
>private - even if we made it private, we could make the same mistake
>from a member function). An example:

> // Example 3
> // Work-around (with a bug)
> struct B {
>  static void f();
>  virtual void Vf() { f(); };
> };
> struct D : public B {
>  static void f();
>  virtual void Vf() { f(); };
> };
> void X(B *p) {  // p* might be B or D
>  B::f(); // OK
>  D::f(); // OK
>  p -> Vf();  // OK
>  p -> f();  // Hard-to-find programmer error:
>     // WRONG if p* is a D!
>     // B::f() is called, we
>     // wanted D::f()
> }

>INFORMALLY, here's a Truth Table that indicates when a static virtual
>would have "virtual" behavior:
>    Calling syntax:
>  B::f()  p->f() or r.f()  f()
>Called from: ================================================
>Outside of class| 1   2  3
>static memfct  | 1   2  4
>nonstatic memfct| 1   2  5
>where B::f() is a static virtual, and B *p, B r&.
>1: unambiguous - same as static non-virtual.
>2: dispatch virtually through the object (similarly to a nonstatic
>virtual)
>3: ill-formed, class is not known.
>4: same as static non-virtual (call f() for the class of the memfct)
>5: dispatch virtually through (*this) (same as nonstatic virtual)
>Again, this is natural and consistent with existing aspects of C++.

See also:  Up further where I figure the pointer to these functions should
have virtual behavior.

>A couple of asides:
>1) I heartily endorsed the concept of const member functions when they
>"appeared" (although several of my programmers objected - too
>confining,
>too much hassle or "false" protection). It both forced the developers
>to
>think more up-front about their code design and it allowed the compiler
>to assist maintenance programmers from making "intent" mistakes by
>preventing them from changing data they shouldn't (bugs which were
>difficult to find). As a const member function can't "change" the
>object, I view a static member function as not being able to even
>"examine" the object (i.e. there is no object). However, developers
>needing "virtual" capability short-circuit this by making what should
>be static member functions nonstatic (see "Design Patterns" -
>Gamma et. al page 115 for an example). Thus, there is less protection
>against maintenance programmers using data they shouldn't. Having
>static virtual would allow us to make a clean distinction as to
>when/why to use static member functions.

Though from a current thread in comp.lang.c++ it seems that people
also want the ability to have template member functions that do not
change their input type but instead change only which which derived
class they are members of.  Which would be one safe case in which to
allow template virtual member functions, of any type.  It would also
be useful for non virtual member functions.  An ability similiar to
the one I mention would with static virtual functions complete
C++ support for generic patterns.

>2) I remember the first time I heard of an inline virtual
>function. I thought that made no sense since inline is inherently a
>compile-time (early) binding and virtual implied a run-time (late)
>binding. I had to play with it a bit to understand the value.
>I think static virtual is similar. At first it doesn't make sense
>(virtual requires an object, static doesn't have an object).
>But if viewed as allowing late binding (through an object) to the
>appropriate static member function, it does make sense.




>D&E "Criteria"
>-----------------------------------------------------------------------
>------

>> [1] Is it precise? (Can we understand what you are suggesting?) Make
>>  a clear, precise statement of the change as it affects the
>current
>>  draft of the language reference standard.

>>From the above, I trust you'll understand what I'm suggesting.
>I can't be certain that I didn't miss any neccessary changes in the
>draft.

>> [a] What changes to the grammar are needed?

>Identified above

>> [b] What changes to the description of the language semantics are
>needed?

>Identified above.

>> [c] Does it fit with the rest of the language?

>Yes - C++ has done a good job of preventing coupling between
>orthogonal features. I view "static" and "virtual" as orthogonal.
>See Example 3 above, as well as the 1st "aside".

>> [2] What is the rationale for the extension? (Why do you want it, and
>why
>>  would we also want it?)

>> [a] Why is the extension needed?

>(Not an extension - we're taking a restriction out. I like
>"simplification".)
>See above. Basically, I view it as useful. I view the
>present prohibition as un-necessary.

>> [b] Who is the audience for the change?

>There is limited direct support for this change (see "From
>comp.std.c++",
>below).
>However, this is a general purpose change. Possibly useful to a
>significant
>minority of programmers who currently use both virtual functions and
>static functions.
>Useful to programmers who segregate "class methods" from "instance
>methods"
>and are looking for polymorphic "class methods" (thus, I see
>wide-spread
>OO potential - but this hasn't materalized during discussions on the
>net).



>> [c] Is this a general-purpose change?

>Yes!

>> [d] Does it affect one group of C++ language users more than others?

>Unsure. (I believe the usefullness of virtual static is more common on
>larger designs where more effort may be spent on isolating class from
>object behavior. But this is an unsupportable opinion.)

>> [e] Is it implementable on all reasonable hardware and systems?

>Yes.

>> [f] Is it useful on all reasonable hardware and systems?

>Yes.

>> [g] What kinds of programming and design styles does it support?

>Factory methods.  Object - oriented: supports polymorphic behavior on
>classes (not just on objects).

>> [h] What kinds of programming and design styles does it prevent?

>No changes from the Draft without this change.

>> [i] What other languages (if any) provide such features?

>I have not used any that do. I understand the ObjectPascal (Delphi)
>supports this.

>> [j] Does it ease the design, implementation, or use of libraries?

>Unsure.

>> [3] Has it been implemented? (If so, has it been implemented in the
>exact
>>  form that you are suggesting; and if not, why can you assume that
>>  experience from "similar" implementations or other languages will
>>  carry over to the features as proposed?)

>No (not to my knowledge.)

>> [a] What effect does it have on a C++ implementation?

>> [i] on compiler organization?

>Not sure (expect minimal effect).

>> [ii] on run-time support?
minor effect of a new pointer type!!
>Not sure (expect no effect).

>> [b] Was the implementation complete?

>Not implemented.

>> [c] Was the implementation used by anyone other than the
>implementer(s)?

>N/A

>> [4] What difference does the feature have on code?

>> [a] What does the code look like without the change?

>See Example 3 above. Typically the code has 2 similar member
>functions - one is virtual, the other is static. The virtual simply
>calls
>the static.

>> [b] What is the effect of not doing the change?

>I'll whimper about C++ growing without polishing the details. (But I'll
>get over it.) Also, I'll have to give an occaisional explanation to
>maintenance programmers on why I didn't code it more simply.

>> [c] Does use of the new feature lead to demands for new support
>tools?

>No.

>> [5] What impact does the change have on efficiency and compatibility
>with
> C and existing C++?

>No impacts on efficiency or compatibility!
Possibly an improvement, and the address of the function can be taken
using a specific object and later calls can suffer one less level of
indirection.

>> [a] How does the change affect run-time efficiency?

>> [i] of the code uses the new feature?

>No worse then a non-member virtual function.

>> [ii] of code that does not use the feature?

>No change.

>> [b] How does the change affect compile and link times?

>Negligible.

>> [c] Does the change affect existing programs?

>> [i] Must C++ code that does not use the feature be recompiled?

>No.

>> [ii] Does the change affect linkage to languages such as C and
>Fortran?

>No.

>> [d] Does the change affect the degree of static or dynamic checking
>> possible for C++ programs?

>No.

>> [6] How easy is the change to document and teach?

>> [a] to novices?

>Trivial -  people assume they can do virtual static until they try it.
>It's harder to teach them about the Draft as it is today.

>> [b] to experts?

>I believe it is difficult to teach a C++ expert anything. ;-)

>> [7] What reasons could there be for not making the extension? There
>will
>>  be counter-arguments and part of our job is to find and evaluate
>>  them, so you can just as well save time be presenting a
>discussion.

>I know of no technical reason nor language usability or consistency
>reason
>why this "extension" should be made. I did use comp.std.c++ to attempt
>to find such reasons.
>Most counter arguments I've heard are naive - they assume a
>contradiction
>between virtual (requires an object) and static (no object).

>There has also been the argument that it is "too late in the game" for
>this change. I'm assuming that is untrue (for relatively minor issues
>such as this), otherwise this "public comment" period would be an
>insincere gesture.

>> [a] Does it affect old code that does not use the construct?

>No

>> [b] Is it hard to learn?

>No

>> [c] Does it lead to demands for further extensions?

>Of course!
>Discussion of static virtual generally leads to 2 related topics:
>1) ability for a base constructor to call a more derived
>static virtual member function and
>2) static virtual data members (and possibly even nonstatic virtual
>data members).

>I now think these should NOT be standardized now. Although #1 makes
>sense from a programmer's perspective, it is not compatible with the
>way (I believe) many implementations manage the vtable during execution
>of base constructors.  Thus, there would be significant added
>implementation complexity unwarrented by the current demand for this
>feature.

>#2 also makes sense from a programmer's perspective (and possibly also
>from an implementer's). There have been convincing arguments that
>static
>virtual data members could readily implemented into a class's
>vtable (assuming that implementation) and that most other issues, such
>as name resolution, etc. have already been worked out for virtual and
>static members. However, I've seen no attempt to identify the
>relevant sections of the draft. There are also (possibly naive)
>concerns
>that this change might also have unforeseen semantic issues - and
>therefore
>is probably too risky to standardize at this time.

>> [d] Does it lead to larger compilers?

>Not sure. But certainly not significantly larger. (Might be smaller -
>they
>have 1 less error message!)

>> [e] Does it require extensive run-time support?

>None.

>> [8] Are there

>> [a] Alternative ways of providing a feature to serve the need?

>Other then the hokey double function approach at the user level
>(Example 3), I'm not aware of any reasonable alternative.

>> [b] Alternative ways of using the syntax suggested?

>Not applicable.

>> [c] Attractive generalizations of the suggested scheme?

>This is a generalization.






>>From comp.std.c++
>-----------------------------------------------------------------------
>------
>In an attempt to determine the merit of the static virtual concept, and
>to determine if there was any support, I've used comp.std.c++ as
>a forum to explore this issue.
>Over the past few weeks there have been about 25 postings regarding
>static virtual, by about 15 different posters. Threads diverged along
>a number of tangents.

>Regarding a posting I made requesting specific input for
>this "public comment" I received 10 replies (9 e-mail, 1 posting that
>wasn't e-mailed). Responses originated from 4 countries, and
>judging from the e-mail addresses, 9 companies or sites.
>I requested opinions on
> 1) static virtual member functions:
>  8 in favor, 2 opposed (note, 1 response was in-favor
>  of this as a pre-requesite for #2, I'm not sure if his
>  support is independent of #2)
> 2) also allowing the base constructor to call the most derived
>  static virtual function:
>  5 in favor, 4 opposed, 1 undecided
> 3) also supporting static virtual data members:
>  2 in favor (1 strongly, 1 weakly), 6 opposed, 2 uncertain
>  or unstated)
>(the counts exclude my postion which is now for #1 only).
>The period of this very unscientific survey was June 29 through July 4
>(a relatively short period considering holidays and vacations).








Author: matt@godzilla.EECS.Berkeley.EDU
Date: 1995/07/07
Raw View
In article <3tih38$nsm@ixnews5.ix.netcom.com> donorgan@ix.netcom.com (Don Organ) writes:

> > [c] Does it fit with the rest of the language?
>
> Yes - C++ has done a good job of preventing coupling between
> orthogonal features. I view "static" and "virtual" as orthogonal.
> See Example 3 above, as well as the 1st "aside".

I don't think this is true: static and virtual aren't at all
orthogonal.  A static member function is a member function that
belongs to a class as a whole rather than to any particular object.  A
virtual member function is a function where the actual function called
at runtime depends on the class of the object through which it is
called.  You can't have a function that's both of these.

What people really want, I think, isn't a static virtual function
(since that doesn't make sense) but rather two functions of the same
name, one of which is static and one of which is virtual, where the
compiler automatically generates both functions given a single
definition.  In some cases, like taking the address, you really have
to think of them as two separate functions.

So let's think about this as an overloading question.  Some types of
overloading (like overloading on return type) are forbidden because
it's not always possible to tell from context which function should be
called, while other types (like overloading on number of arguments) is
allowed.  Which category does overloading on static fall into?  Are
there any potential ambiguities?

This really isn't such a big deal, anyway.  I have occasionally wanted
"static virtual" functions.  I couldn't have a static and a virtual
member function with the same names, so I just used two different
names.  That's not a major inconvenience.
--
Matt Austern          matt@physics.berkeley.edu
http://dogbert.lbl.gov/~matt