🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.std.c++
Article #3379

Re: Q: Generic Callbacks -- "Object->*func(...)"

#3379
From: Ben Jones
Date: Wed, 21 Feb 1996 17:50
119 lines
4213 bytes
brian (b.c.) white (bcwhite@bnr.ca) wrote:
: Does the C++ standard allow for a generic callback to be specified?

: Basically, I'd like to be able to pass an arbitrary object and function of
: that object to be called at some later time.  For example:

: void DoIt(ANYOBJECT* Object, void (ANYOBJECT::*CallBack)( ...parmlist... ))
: {
: 	[...]
: 	Object->*CallBack( ...parms... );
: 	[...]
: }


: I'd like to be able to call "DoIt" with any type of object and a pointer to
: any of that object's member functions that match the 'parmlist'.  As it
: stands, any object passed in would have to be in the same class hierarchy
: as ANYOBJECT, thus basically requiring a unified class hierachy in order to
: do this genericly.

: [snip snip]

: So...  Is this possible?


The following kluge works on all platforms that I have tried it on
including Sun, SGI, Alpha, Macintosh, PC:

    #include <stdarg.h>

    class Callback
    {
    public:
      typedef void (Callback::*MF)();
      typedef void (*F)();

      Callback(F ff=0)
	{
	  p = 0;
	  f = ff;
	}
      Callback(void *pp,...)
	{
	  va_list ap; va_start(ap,pp);
	  p=(Callback*)pp;
	  mf = va_arg(ap,MF);
	}
      virtual void operator()()
	{
	  if (p)
	    (p->*mf)();
	  else if (f)
	    f();
	}

    private:
      Callback *p;
      union { MF mf; F f; };
    };

Essentially, the "Callback" class consists of an object pointer and a
function pointer.  The constructors provide for two cases: a global
function (which causes a null object pointer to be stored) or a paired
object and member function pointer.  The parenthesis operator is
overloaded so that a Callback object may be executed as though it were
a function pointer.  It is declared virtual so that virtual callback
functions will work properly.

Now we can set up a callback very easily:

    Callback mycallback;
        ...
    mycallback = function;
        ...
    mycallback = Callback(&object,&classname::memberfunction);
        ...
    mycallback();

The above class can be defined with a template or macro such that
you can make variations on it for callback functions with various
argument types.

It is not typesafe.  It is your responsibility to make sure that
"object" and "memberfunction" are compatible.  However, as I said
before, it works everywhere that I've tried it.

    ------------

A simple extension to C++ would allow for a perfectly typesafe
callback scheme.  All that is necessary is that the following
expressions:

    object.function
    pointer->function

be LEGAL without having to be followed by ().  For them to be
legal there needs to be a container which can hold the values
of those expressions.  I would suggest:

    type (::*callback)(type1,type2,...)

That is, if you specify "::*" without a qualifying classname,
then "callback" can accept an expression like "object.function"
provided that "function" has a prototype of "type(type1,type2,..)".
Simple as that.

ANSI commitee please take note.

Ben Jones
Hughes Information Technology
bjones@eos.hitc.com
jones@cais.com
---
[ To submit articles: Try just posting with your newsreader.  If that fails,
                      use mailto:std-c++@ncar.ucar.edu
  FAQ:    http://reality.sgi.com/employees/austern_mti/std-c++/faq.html
  Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu 
]
Technical Details
Message-ID: <4gfdck$i0g@zippy.cais.net>
Path: arc1-ca.pugleaf.net!chronicle.mti.sgi.com!austern
References: <4fti32$p3p@bcarh8ab.bnr.ca>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!chronicle.mti.sgi.com!austern
From: jones@cais.cais.com (Ben Jones)
Newsgroups: comp.std.c++
Subject: Re: Q: Generic Callbacks -- "Object->*func(...)"
Date: 21 Feb 1996 09:50:36 PST
Organization: Capital Area Internet Service info@cais.com 703-448-4470
Approved: austern@isolde.mti.sgi.com
Message-ID: <4gfdck$i0g@zippy.cais.net>
References: <4fti32$p3p@bcarh8ab.bnr.ca>
NNTP-Posting-Host: isolde.mti.sgi.com
X-Original-Date: 21 Feb 1996 15:23:00 GMT
X-Newsreader: TIN [version 1.2 PL2]
X-Auth: PGPMoose V1.1 PGP comp.std.c++
 iQBVAwUBMStbmEy4NqrwXLNJAQETwQIAmk+iMfjzJ9J9eWwRTysUcfjhUKnQ0U9j
 JDMFC4YaVYqv0/LNp1jCF46owo3wSwrUySlSt2/eRy6hi5Rrrf56YQ==
 =AlDY
Originator: austern@isolde.mti.sgi.com