From: jamshid@ut-emx.uucp (Jamshid Afshar)
Newsgroups: comp.lang.c++
Subject: Re: How do I write a typedef to go with my template class?
Keywords: template generic define
Date: 27 Aug 92 23:41:15 GMT
Organization: The University of Texas at Austin; Austin, Texas

In article <ghawkins.714856261@unix1.tcd.ie> ghawkins@unix1.tcd.ie (George C. Hawkins) writes:
>	template <class X>
>	class Callback {
>		...
>	}
>	typedef void (X::func_ptr)(int);
>
>And even if I could I'd get name clashes for all my typedefs for
>Callback class being used with different X types.

The best you can do is a nested typedef (but at least that solves the
naming problem).

	template<class X>
	class Callback {
	public:
	   typedef void (X::*PMF)(int);   // defines nested type name "PMF"
	   Callback(X* x, PMF f) { ... }
	   ...
	};

	CallBack<Foo>::PMF mfp = &Foo::doit;  // define 'mfp' variable
	Foo afoo;
	Callback c(&afoo, mfp);  // defines callback 'c'

Warning, BC++ has trouble with nested typedefs.  Also, I'm appending
my callback class templates.  See functor1.h for the (sparse)
documentation and usage examples.

Jamshid Afshar
jamshid@emx.utexas.edu

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  functor0.h functor1.h functor2.h smartptr.h tstftor.cpp
# Wrapped by jamshid@emx.utexas.edu on Mon Mar 23 14:55:15 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'functor0.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'functor0.h'\"
else
echo shar: Extracting \"'functor0.h'\" \(3334 characters\)
sed "s/^X//" >'functor0.h' <<'END_OF_FILE'
X/****************************************************************************
X*  File: functor0.h
X*  
X*  Description:
X*     Defines the Functor0<R> class template and Functor0v class and the
X*     functor(O*, R (O::*)()) and functorv(O*, void (O::*)()) function
X*     templates which create the Functor objects.  These are Functors
X*     taking zero parameters.  See functor1.h for a description of Functors.
X*
X*  Usage:
X*     See functor1.h
X*
X*  Notes:
X*     See functor1.h.  Functor0v is not a template.
X*
X*  History:
X*  14 Feb 1992 Jam      created from functor1.h -- replaced "{, }@class P1",
X*                       "P1 p1", "{, }P1>", "P1)", "p1"
X*  19 Feb 1992 Jam      renamed functorN() back to functor(), overloadable:-)
X*  20 Mar 1992 Jam      added null() and void* conversion: `if (f1)'
X*  20 Mar 1992 Jam      restructured -- Functor1 now contains ptr
X*     
X****************************************************************************/     
X#ifndef JAM_FUNCTOR0_H
X#define JAM_FUNCTOR0_H
X
X#include "smartptr.h"
X
X//**************************************************************************
X// Defines Functor0<R>, functor(O*, R (O::*)()) and helper classes
X//**************************************************************************
X
X   template<class R>
Xclass AbstractFunctor0 : public JAM_ReferenceCounter {
Xpublic:
X   virtual R call() const = 0;
X   virtual int null() const = 0;
X};
X
X   template<class R>
Xclass Functor0 {
X   JAM_SmartPtr< AbstractFunctor0<R> > _ptr;
Xpublic:
X   Functor0(AbstractFunctor0<R>* ptr = 0) : _ptr(ptr) {}
X   R operator()() const { return _ptr->call(); }
X   operator const void*() const
X      { return (_ptr==0 || _ptr->null()) ? 0 : this; }
X};
X
X   template<class O, class R>
Xclass ConcreteFunctor0 : public AbstractFunctor0<R> {
Xpublic:
X   ConcreteFunctor0(O* object, R (O::*method)())
X      : _object(object), _method(method) {}
X   virtual R call() const { return (_object->*_method)(); }
X   virtual int null() const { return _object==0 || _method==0; }
Xprotected:
X   O* _object;
X   R (O::*_method)();
X};
X
X   template<class O, class R> inline
XFunctor0<R> functor(O* object, R (O::*method)()) {
X   return new ConcreteFunctor0<O, R>(object, method);
X}
X
X
X//**************************************************************************
X// Defines Functor0v, functorv(O*, void (O::*)()) and helper classes
X//**************************************************************************
X
Xclass AbstractFunctor0v : public JAM_ReferenceCounter {
Xpublic:
X   virtual void call() const = 0;
X   virtual int null() const = 0;
X};
X
Xclass Functor0v {
X   JAM_SmartPtr< AbstractFunctor0v > _ptr;
Xpublic:
X   Functor0v(AbstractFunctor0v* ptr = 0) : _ptr(ptr) {}
X   void operator()() const { _ptr->call(); }
X   operator const void*() const
X      { return (_ptr==0 || _ptr->null()) ? 0 : this; }
X};
X
X   template<class O>
Xclass ConcreteFunctor0v : public AbstractFunctor0v {
Xpublic:
X   ConcreteFunctor0v(O* object, void (O::*method)())
X      : _object(object), _method(method) {}
X   virtual void call() const { (_object->*_method)(); }
X   virtual int null() const { return _object==0 || _method==0; }
Xprotected:
X   O* _object;
X   void (O::*_method)();
X};
X
X   template<class O> inline
XFunctor0v functorv(O* object, void (O::*method)()) {
X   return new ConcreteFunctor0v<O>(object, method);
X}
X
X
X#endif // JAM_FUNCTOR0_H
X
END_OF_FILE
if test 3334 -ne `wc -c <'functor0.h'`; then
    echo shar: \"'functor0.h'\" unpacked with wrong size!
fi
# end of 'functor0.h'
fi
if test -f 'functor1.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'functor1.h'\"
else
echo shar: Extracting \"'functor1.h'\" \(5011 characters\)
sed "s/^X//" >'functor1.h' <<'END_OF_FILE'
X/****************************************************************************
X*  File: functor1.h
X*  
X*  Description:
X*     Defines Functor1<R, P1> and Functor1v<P1> class templates and
X*     functor(O*, R (O::*)(P1)) and functorv(O*, void (O::*)(P1)) function
X*     templates which create Functor objects.  A Functor is used as if
X*     it were a pointer to a function taking a P1 parameter and returning
X*     an R.  Functor1v is just like Functor1 except it returns void
X*     (there is no R).
X*     
X*     Functors actually contain a pointer to an object and a pointer to one
X*     of the object's member functions.  These two pointers are specified
X*     when calling functor().  The member function must take a parameter P1
X*     and returns R.  When the Functor is executed, that member function is
X*     called on the object.  Since the code using a Functor only has to
X*     specify the type of the member function parameters and return type,
X*     not the type of the object actually receiving the message, using
X*     Functors makes the code more general.
X*
X*
X*  Usage:
X*     class Foo {
X*     public:
X*        int addstr(const String& newstr);
X*        void scroll(double percent);
X*     } afoo;
X*     Functor1<int, const String&> f1 = functor(&afoo, &Foo::addstr);
X*     if ( f1("new entry")==0 ) cerr << "Couldn't add string.\n";
X*     Functor1v<double> f2 = functorv(&afoo, &Foo::scroll);
X*     f2(0.5);    // scroll Foo by 50%
X*     Functor1v<double> f3 = 0;
X*     if (f3!=0) f3(1.23);
X*
X*  Notes:
X*     Below, the template parameter O is the type of the object whose
X*     member function will be called.  The return type of the member
X*     function is R (but there is none for Functor1v).  The member
X*     function takes one parameter of type P1.
X*
X*  History:
X*  12 Feb 1992 Jam      created; referenced Coplien
X*  13 Feb 1992 Jam      added operator() functionality to a derived SmartPtr
X*  13 Feb 1992 Jam      added Functor1v for functors returning void (no R)
X*  14 Feb 1992 Jam      renamed functor[v]() functor1[v]() because of functor2.h
X*  19 Feb 1992 Jam      renamed functorN() back to functor(), overloadable:-)
X*  20 Mar 1992 Jam      added null() and void* conversion: `if (f1)'
X*  20 Mar 1992 Jam      restructured -- Functor1 now contains a ptr
X*                       instead of inheriting from it
X*     
X****************************************************************************/     
X#ifndef JAM_FUNCTOR1_H
X#define JAM_FUNCTOR1_H
X
X#include "smartptr.h"
X
X//**************************************************************************
X// Defines Functor1<R, P1>, functor(O*, R (O::*)(P1)) and helper classes
X//**************************************************************************
X
X   template<class R, class P1>
Xclass AbstractFunctor1 : public JAM_ReferenceCounter {
Xpublic:
X   virtual R call(P1 p1) const = 0;
X   virtual int null() const = 0;
X};
X
X   template<class R, class P1>
Xclass Functor1 {
X   JAM_SmartPtr< AbstractFunctor1<R, P1> > _ptr;
Xpublic:
X   Functor1(AbstractFunctor1<R, P1>* ptr = 0) : _ptr(ptr) {}
X   R operator()(P1 p1) const { return _ptr->call(p1); }
X   operator const void*() const
X      { return (_ptr==0 || _ptr->null()) ? 0 : this; }
X};
X
X   template<class O, class R, class P1>
Xclass ConcreteFunctor1 : public AbstractFunctor1<R, P1> {
Xpublic:
X   ConcreteFunctor1(O* object, R (O::*method)(P1))
X      : _object(object), _method(method) {}
X   virtual R call(P1 p1) const { return (_object->*_method)(p1); }
X   virtual int null() const { return _object==0 || _method==0; }
Xprotected:
X   O* _object;
X   R (O::*_method)(P1 p1);
X};
X
X   template<class O, class R, class P1> inline
XFunctor1<R, P1> functor(O* object, R (O::*method)(P1)) {
X   return new ConcreteFunctor1<O, R, P1>(object, method);
X}
X
X
X//**************************************************************************
X// Defines Functor1v<P1>, functorv(O*, void (O::*)(P1)) and helper classes
X//**************************************************************************
X
X   template<class P1>
Xclass AbstractFunctor1v : public JAM_ReferenceCounter {
Xpublic:
X   virtual void call(P1 p1) const = 0;
X   virtual int null() const = 0;
X};
X
X   template<class P1>
Xclass Functor1v {
X   JAM_SmartPtr< AbstractFunctor1v<P1> > _ptr;
Xpublic:
X   Functor1v(AbstractFunctor1v<P1>* ptr) : _ptr(ptr) {}
X   void operator()(P1 p1) const { _ptr->call(p1); }
X   operator const void*() const
X      { return (_ptr==0 || _ptr->null()) ? 0 : this; }
X};
X
X   template<class O, class P1>
Xclass ConcreteFunctor1v : public AbstractFunctor1v<P1> {
Xpublic:
X   ConcreteFunctor1v(O* object, void (O::*method)(P1))
X      : _object(object), _method(method) {}
X   virtual void call(P1 p1) const { (_object->*_method)(p1); }
X   virtual int null() const { return _object==0 || _method==0; }
Xprotected:
X   O* _object;
X   void (O::*_method)(P1 p1);
X};
X
X   template<class O, class P1> inline
XFunctor1v<P1> functorv(O* object, void (O::*method)(P1)) {
X   return new ConcreteFunctor1v<O, P1>(object, method);
X}
X
X
X#endif // JAM_FUNCTOR1_H
X
END_OF_FILE
if test 5011 -ne `wc -c <'functor1.h'`; then
    echo shar: \"'functor1.h'\" unpacked with wrong size!
fi
# end of 'functor1.h'
fi
if test -f 'functor2.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'functor2.h'\"
else
echo shar: Extracting \"'functor2.h'\" \(3824 characters\)
sed "s/^X//" >'functor2.h' <<'END_OF_FILE'
X/****************************************************************************
X*  File: functor2.h
X*  
X*  Description:
X*     Defines the Functor2<R, P1, P2> and Functor2v<P1, P2> class
X*     templates and the functor(O*, R (O::*)(P1, P2)) and
X*     functorv(O*, void (O::*)(P1, P2)) function templates which create
X*     the Functor objects.  These are Functors taking two parameters
X*     See functor1.h for a description of Functors.
X*
X*
X*  Usage:
X*     See functor1.h
X*
X*  Notes:
X*     See functor1.h
X*
X*  History:
X*  14 Feb 1992 Jam      created from functor1.h -- replaced "class P1",
X*                       "P1 p1", "P1>", "P1)", "p1)"
X*  14 Feb 1992 Jam      had to rename functor[v]() functor2[v]()
X*  19 Feb 1992 Jam      renamed functorN() back to functor(), overloadable:-)
X*  20 Mar 1992 Jam      added null() and void* conversion: `if (f1)'
X*  20 Mar 1992 Jam      restructured -- Functor1 now contains ptr
X*     
X****************************************************************************/     
X#ifndef JAM_FUNCTOR2_H
X#define JAM_FUNCTOR2_H
X
X#include "smartptr.h"
X
X//**************************************************************************
X// Defines Functor2<R, P1, P2>, functor(O*, R (O::*)(P1, P2)) and helper classes
X//**************************************************************************
X
X   template<class R, class P1, class P2>
Xclass AbstractFunctor2 : public JAM_ReferenceCounter {
Xpublic:
X   virtual R call(P1 p1, P2 p2) const = 0;
X   virtual int null() const = 0;
X};
X
X   template<class R, class P1, class P2>
Xclass Functor2 {
X   JAM_SmartPtr< AbstractFunctor2<R, P1, P2> > _ptr;
Xpublic:
X   Functor2(AbstractFunctor2<R, P1, P2>* ptr = 0) : _ptr(ptr) {}
X   R operator()(P1 p1, P2 p2) const { return _ptr->call(p1, p2); }
X   operator const void*() const
X      { return (_ptr==0 || _ptr->null()) ? 0 : this; }
X};
X
X   template<class O, class R, class P1, class P2>
Xclass ConcreteFunctor2 : public AbstractFunctor2<R, P1, P2> {
Xpublic:
X   ConcreteFunctor2(O* object, R (O::*method)(P1, P2))
X      : _object(object), _method(method) {}
X   virtual R call(P1 p1, P2 p2) const { return (_object->*_method)(p1, p2); }
X   virtual int null() const { return _object==0 || _method==0; }
Xprotected:
X   O* _object;
X   R (O::*_method)(P1 p1, P2 p2);
X};
X
X   template<class O, class R, class P1, class P2> inline
XFunctor2<R, P1, P2> functor(O* object, R (O::*method)(P1, P2)) {
X   return new ConcreteFunctor2<O, R, P1, P2>(object, method);
X}
X
X
X//**************************************************************************
X// Defines Functor2v<P1, P2>, functorv(O*, void (O::*)(P1, P2)) and helper classes
X//**************************************************************************
X
X   template<class P1, class P2>
Xclass AbstractFunctor2v : public JAM_ReferenceCounter {
Xpublic:
X   virtual void call(P1 p1, P2 p2) const = 0;
X   virtual int null() const = 0;
X};
X
X   template<class P1, class P2>
Xclass Functor2v {
X   JAM_SmartPtr< AbstractFunctor2v<P1, P2> > _ptr;
Xpublic:
X   Functor2v(AbstractFunctor2v<P1, P2>* ptr = 0) : _ptr(ptr) {}
X   void operator()(P1 p1, P2 p2) const { _ptr->call(p1, p2); }
X   operator const void*() const
X      { return (_ptr==0 || _ptr->null()) ? 0 : this; }
X};
X
X   template<class O, class P1, class P2>
Xclass ConcreteFunctor2v : public AbstractFunctor2v<P1, P2> {
Xpublic:
X   ConcreteFunctor2v(O* object, void (O::*method)(P1, P2))
X      : _object(object), _method(method) {}
X   virtual void call(P1 p1, P2 p2) const { (_object->*_method)(p1, p2); }
X   virtual int null() const { return _object==0 || _method==0; }
Xprotected:
X   O* _object;
X   void (O::*_method)(P1 p1, P2 p2);
X};
X
X   template<class O, class P1, class P2> inline
XFunctor2v<P1, P2> functorv(O* object, void (O::*method)(P1, P2)) {
X   return new ConcreteFunctor2v<O, P1, P2>(object, method);
X}
X
X
X#endif // JAM_FUNCTOR2_H
X
END_OF_FILE
if test 3824 -ne `wc -c <'functor2.h'`; then
    echo shar: \"'functor2.h'\" unpacked with wrong size!
fi
# end of 'functor2.h'
fi
if test -f 'smartptr.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'smartptr.h'\"
else
echo shar: Extracting \"'smartptr.h'\" \(4533 characters\)
sed "s/^X//" >'smartptr.h' <<'END_OF_FILE'
X/****************************************************************************
X*  File: smartptr.h
X*  
X*  Description:  JAM_ReferenceCounter class definition
X*                JAM_SmartPtr template class
X*     
X*     A JAM_SmartPtr<T> object is just like a pointer but you don't have to
X*     worry about memory leaks because it counts references.  Because
X*     JAM_SmartPtrs behave just like regular pointers, they can alias the
X*     same object.  T must derive from public JAM_ReferenceCounter (defined
X*     above).  
X*
X*  Notes:
X*     I have no idea how any of this would work when dealing with virtual
X*     bases (MI).
X*
X*
X*  History:
X*  20 Dec 1991 Jam      created from my <generic.h> macro
X*  12 Feb 1992 Jam      had to move defs of all SmartPtr funcs out of class
X*                       because of a BC++ 3.0 bug when using functors
X*  14 Feb 1992 Jam      made ~JAM_ReferenceCounter protected to prevent
X*                       users from using delete
X*  20 Mar 1992 Jam      changed operator void* to const void* for safety
X*     
X****************************************************************************/     
X
X#ifndef JAM_SMARTPTR_H
X#define JAM_SMARTPTR_H
X
X#include <assert.h>
X
X//***************************************************************************
X// JAM_ReferenceCounter definition
X//***************************************************************************
X
Xclass JAM_ReferenceCounter {
Xprivate:
X   int _numrefs;     // number of SmartPtrs referencing me
X   JAM_ReferenceCounter(const JAM_ReferenceCounter&); // hide me -- can't copy
X   void operator=(const JAM_ReferenceCounter&);     // hide me -- can't copy
Xprotected:
X      // keep dtors protected so user can't `delete p;' -- we
X      // delete ourselves if you only use SmartPtrs
X   virtual ~JAM_ReferenceCounter() { assert(_numrefs==0); }
Xpublic:
X   JAM_ReferenceCounter() : _numrefs(0) {}
X   int numRefs() const { return _numrefs; }
X   void incRefs() { ++_numrefs; }
X   void decRefs() {
X      assert(_numrefs>0);
X      if (--_numrefs==0) delete this;
X      }
X};
X
X
X//***************************************************************************
X// JAM_SmartPtr definition
X//***************************************************************************
X
Xtemplate<class T> class JAM_SmartPtr {
Xpublic:
X   JAM_SmartPtr();
X
X   /* itemp MUST BE ON HEAP.  Do not use itemp after assignment. */
X   JAM_SmartPtr(T* itemp); 
X
X   JAM_SmartPtr(const JAM_SmartPtr<T>& smrt); 
X
X   ~JAM_SmartPtr(); 
X
X   void operator=(const JAM_SmartPtr<T>& smrt); 
X
X   /* itemp MUST BE ON HEAP.  Do not use itemp after assignment */
X   void operator=(T* itemp); 
X
X   /* does *NOT* call T == T */
X   int operator==(const JAM_SmartPtr<T>& smrt); 
X
X   const T* operator->() const; 
X   const T& operator*() const; 
X
X   T* operator->(); 
X   T& operator*(); 
X
X   operator const void*() const { return _ptr; } // Borland bug doesn't allow definition outside
X
Xprotected:
X   T* _ptr;
X};
X
X
X//***************************************************************************
X// JAM_SmartPtr inlines
X//***************************************************************************
X
Xtemplate<class T> inline
XJAM_SmartPtr<T>::JAM_SmartPtr()
X   : _ptr(0) {}
X
Xtemplate<class T> inline
XJAM_SmartPtr<T>::JAM_SmartPtr(T* itemp)
X   : _ptr(itemp) { if (_ptr) _ptr->incRefs(); }
X
X
Xtemplate<class T> inline
XJAM_SmartPtr<T>::JAM_SmartPtr(const JAM_SmartPtr<T>& smrt)
X   : _ptr(smrt._ptr) { if (_ptr) _ptr->incRefs(); }
X
X
Xtemplate<class T> inline
XJAM_SmartPtr<T>::~JAM_SmartPtr() {
X   if (_ptr) { _ptr->decRefs(); _ptr=0; }
X}
X
Xtemplate<class T> inline
Xvoid JAM_SmartPtr<T>::operator=(const JAM_SmartPtr<T>& smrt) {
X   if (this==&smrt || _ptr==smrt._ptr) return;
X   if (_ptr) _ptr->decRefs();
X   _ptr = smrt._ptr;
X   if (_ptr) _ptr->incRefs();
X}
X
X
Xtemplate<class T> inline
Xvoid JAM_SmartPtr<T>::operator=(T* itemp) {
X   assert(_ptr!=itemp); /* weird stuff happening */
X   if (_ptr) _ptr->decRefs();
X   _ptr = itemp;
X   if (_ptr) _ptr->incRefs();
X}
X
X
Xtemplate<class T> inline
Xint JAM_SmartPtr<T>::operator==(const JAM_SmartPtr<T>& smrt) {
X   return _ptr==smrt._ptr;
X}
X
X
Xtemplate<class T> inline
Xconst T* JAM_SmartPtr<T>::operator->() const {
X   assert(_ptr != 0); return _ptr;
X}
X
X
Xtemplate<class T> inline
Xconst T& JAM_SmartPtr<T>::operator*() const {
X   assert(_ptr != 0); return *_ptr;
X}
X
X
Xtemplate<class T> inline
XT* JAM_SmartPtr<T>::operator->() {
X   assert(_ptr != 0); return _ptr;
X}
X
Xtemplate<class T> inline
XT& JAM_SmartPtr<T>::operator*() {
X   assert(_ptr != 0); return *_ptr;
X}
X
X#endif // JAM_SMARTPTR_H
X
END_OF_FILE
if test 4533 -ne `wc -c <'smartptr.h'`; then
    echo shar: \"'smartptr.h'\" unpacked with wrong size!
fi
# end of 'smartptr.h'
fi
if test -f 'tstftor.cpp' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tstftor.cpp'\"
else
echo shar: Extracting \"'tstftor.cpp'\" \(2354 characters\)
sed "s/^X//" >'tstftor.cpp' <<'END_OF_FILE'
X// Just a simple, meaningless, but pretty comprehensive set of
X// tests for my Functor classes
X// by Jamshid Afshar.  All code is in the public domain.
X
X#include <iostream.h>
X#include <assert.h>
X#include "functor0.h"
X#include "functor1.h"
X#include "functor2.h"
X
Xclass Model {
Xpublic:
X   int save1() { cout << "save1" << endl; return -3; }
X   void save2() { cout << "save2" << endl; }
X   int enter1(const char* s) { cout << s << endl; return -1; }
X   void enter2(char c) { cout << c << endl; }
X   int enterat1(int i, const char* s) { cout << i << ',' << s << endl; return -2; }
X   void enterat2(int i, const char* s) { cout << i << ',' << s << endl; }
X};
X
Xtypedef Functor1<int,const char*> FP1;
Xtypedef Functor1v<char> FP2;
Xtypedef Functor0<int> FP3;
Xtypedef Functor0v FP4;
Xtypedef Functor2<int, int, const char*> FP5;
Xtypedef Functor2v<int, const char*> FP6;
X
Xclass View {
X   FP1 _f1;
X   FP2 _f2;
X   FP3 _f3;
X   FP4 _f4;
X   FP5 _f5;
X   FP6 _f6;
Xpublic:
X   View(const FP1& f1, const FP2& f2, const FP3& f3, const FP4& f4, const FP5& f5, const FP6& f6)
X      : _f1(f1), _f2(f2), _f3(f3), _f4(f4), _f5(f5), _f6(f6) {}
X   void input() {
X      if (_f1) cout << _f1("Hello") << endl;
X      else cout << "_f1==0" << endl;
X      if (_f2) _f2('J');
X      else cout << "_f2==0" << endl;
X      if (_f3) cout << _f3() << endl;
X      else cout << "_f3==0" << endl;
X      if (_f4) _f4();
X      else cout << "_f4==0" << endl;
X      if (_f5) cout << _f5(5, "Str1") << endl;
X      else cout << "_f5==0" << endl;
X      if (_f6) _f6(6, "Str2");
X      else cout << "_f6==0" << endl;
X      }
X};
X
Xmain() {
X   Model m;
X   FP1 f;
X   assert(!f);
X   f = 0; assert(!f);
X   f = functor(&m, &Model::enter1);
X   assert(f);
X   FP1 f2;
X   f = f2; assert(f==0);
X   f = functor(&m, &Model::enter1); assert(f);
X   f = functor((Model*)0, &Model::enter1); assert(!f);
X   f = functor(&m, (int(Model::*)(const char*))0); assert(!f);
X   f = functor(&m, &Model::enter1); assert(f);
X   f = functor((Model*)0, (int(Model::*)(const char*))0); assert(!f);
X   FP1 f3(0);
X   assert(!f3);
X   View v(functor(&m, &Model::enter1), functorv(&m, &Model::enter2),
X         functor(&m, &Model::save1), functorv(&m, &Model::save2),
X         functor(&m, &Model::enterat1), functorv(&m, &Model::enterat2));
X   v.input();
X   View vz(FP1(0), FP2(0), FP3(0), FP4(0), FP5(0), FP6(0));
X   vz.input();
X   return 0;
X}
X
END_OF_FILE
if test 2354 -ne `wc -c <'tstftor.cpp'`; then
    echo shar: \"'tstftor.cpp'\" unpacked with wrong size!
fi
# end of 'tstftor.cpp'
fi
echo shar: End of shell archive.
exit 0
Newsgroups: comp.lang.c++