Topic: Question on the new standard


Author: imp@village.org (Warner Losh)
Date: 1995/05/04
Raw View
I have a question about the new standard.  For years and years
(literally 7 years), many GUI toolkits have provided a "generic"
callback mechanism that relies on the casting of member function
pointers.  For years and years this has been a dark corner of the
language that people never could agree on its meaning (some people
said it was cool, others said it was evil).  Now, it would appear that
those with the latter view have prevailed and that it is now, in fact,
illegal.  While it is good that the committee has produced a position,
it is bad that it works against a large amount of code in place :-(.

I base this statement on the following bit of the standard:
  5.2.8  Static cast                                  [expr.static.cast]
...
9 An rvalue of type "pointer to member of D of type cv1 T" can  be  con-
  verted  to  an  rvalue of type "pointer to member of B of type cv2 T",
  where B is a base class (_class.derived_) of D, if  a  valid  standard
  conversion  from "pointer to member of B of type cv2 T" to "pointer to
  member of D of type cv2 T" exists (_conv.mem_), and cv2  is  the  same
  cv-qualification  as, or greater cv-qualification than, cv1.  The null
  member pointer value (_conv.mem_) is  converted  to  the  null  member
  pointer  value of the destination type.  If class B contains or inher-
                                           *****************************
  its the original member, the resulting pointer to member points to the
  **********************************************************************
  member in class B.  Otherwise, the result of the cast is undefined.
  *******************************************************************
...

(** are mine)

This would seem to clearly indicate that it is the intention of the
committee to outlaw code that looks like:

 class B { public: B(); virutal ~B(); };
 class D : public B { void foo(); }
 typedef void (B::*memfnp)();

 B *b = new D();
 memfnp mp = static_cast<memfnp>(&D::foo);
/* aka memfnp mp = (memfnp) &D::foo; */
 (b->*mp)();

which is used in at least one major C++ class library for its generic
member function callbacks.

My question is, why is there this restriction?  It seems like a
perfectly acceptible thing to do, from my point of view, so I don't
understand it.  I know that the committee sometimes seems to work in
strange ways, but this one is a bit beyond me.  Given the skills of
the people involved, I think that either a) there is a good reason
that can easily be explained, or b) the sentence was tacked on because
it was late in the day and no one wanted to argue :-).

Thank you for your time and consideration...

Warner

P.S.  I know that ET++ and OI (object interface from Openware (was
ParcPlace (was Solbourne))) both use this technique.





Author: rjl@f111.iassf.easams.com.au (Rohan LENARD)
Date: 1995/05/08
Raw View
In article <3oce41$d17@rover.village.org>, Warner Losh <imp@village.org> wrote:
>My question is, why is there this restriction?  It seems like a
>perfectly acceptible thing to do, from my point of view, so I don't
>understand it.  I know that the committee sometimes seems to work in
>strange ways, but this one is a bit beyond me.  Given the skills of
>the people involved, I think that either a) there is a good reason
>that can easily be explained, or b) the sentence was tacked on because
>it was late in the day and no one wanted to argue :-).

Because there are other suitable methods which don't rely on unsafe casts.
eg.
#include <iostream.h>

class CallBack {
public:
  virtual DoCallback(void *,void *) = 0;
};

class MyCallBack : public CallBack {
public:
  DoCallback(void *a,void *b) {
    cerr << "Callback called with a = " << a << ", b = " << b << endl;
  }
};

class Foo {
public:
  AttachCallback(CallBack* pX) { pY = pX; };
  DoCallback(void *a, void *b) { pY->DoCallback(a,b); }
  Foo() : pY(0) {};
private:
  CallBack* pY;
};

main()
{
  Foo a;
  MyCallBack b;

  a.AttachCallback(&b);
  a.DoCallback(0,0);
}


I also have a feeling that there was a vote at Austin to change this to
allow the prior art as well.  Maybe someone else will point out whether
this is so.

Rohan
--
----------------------------------------------------------------------------
rjl@iassf.easams.com.au | All quotes can be attributed to my automated quote
Rohan Lenard            | writing tool.  Yours for just $19.95; and if you
+61-2-367-4555          | call now you'll get a free set of steak knives ...