// lots of "interesting uses of templates"... Is it a bug? #include struct IFoo { virtual void Bar () = 0; }; struct IDitto : public IFoo { virtual void Oops () = 0; }; template class CNonDelegator : public IFoo { Delegatee* m_pThis; public: CNonDelegator ( Delegatee* pThis ) : m_pThis(pThis) { printf ("CNonDelegator::CNonDelegator(): value of this: 0x%x\n", this); printf ("CNonDelegator::CNonDelegator(): value of m_pThis: 0x%x\n", m_pThis ); } void Bar () { printf ("CNonDelegator::Bar(): value of m_pThis: 0x%x\n", m_pThis ); m_pThis->InternalBar (); } }; template class CDelegator : public base { CNonDelegator m_nd; public: CDelegator ( IFoo* pOuter, Deferer* pThis ) : m_nd(pThis) { if ( pOuter ) { printf ("CDelegator::CDelegator(): assigning m_pUnkOuter to pOuter.\n"); #ifdef SET_FOO SetFoo ( pOuter ); #else m_pUnkOuter = pOuter; #endif } else { printf ("CDelegator::CDelegator(): assigning m_pUnkOuter to &m_nd.\n"); #if SET_FOO SetFoo ( &m_nd ); #else m_pUnkOuter = &m_nd; #endif } printf ("CDelegator::CDelegator(): value of m_pUnkOuter: 0x%x\n", m_pUnkOuter ); } void Bar () { printf ("CDelegator::Bar(): value of m_pUnkOuter: 0x%x\n", m_pUnkOuter); m_pUnkOuter->Bar (); } }; template class CUser : public CDelegator > { typedef CDelegator > base_class; public: CUser (IFoo* pOuter ) : base_class (pOuter, this) { printf ("CUser::CUser(): value of m_pUnkOuter: 0x%x\n", m_pUnkOuter ); } void InternalBar () { printf ("CUser::InternalBar() called!\n"); } }; #if FIRST_BUG class FakeAutoCS { public: void Lock() {} void Unlock () {} }; class DefTM { public: static unsigned long Increment ( long* pn ) { return ++(*pn); } static unsigned long Decrement ( long* pn ) { return --(*pn); } typedef FakeAutoCS CriticalSection; typedef FakeAutoCS AutoCriticalSection; }; template class CRootObject { typedef typename tm::CriticalSection CriticalSection; typedef typename tm::AutoCriticalSection AutoCriticalSection; AutoCriticalSection m_cs; public: void Lock() { m_cs.Lock(); } void Unlock() { m_cs.Unlock(); } }; #endif // FIRST_BUG template class CoClass #if FIRST_BUG : public CRootObject #endif // FIRST_BUG { protected: IFoo* m_pUnkOuter; public: CoClass () : m_pUnkOuter(0) { printf ("CoClass::CoClass(): value of this: 0x%x\n", this ); printf ("CoClass::CoClass(): value of m_pUnkOuter: 0x%x\n", m_pUnkOuter); } IFoo* GetFoo() { printf ("CoClass::GetFoo() called: m_pUnkOuter = 0x%x\n",m_pUnkOuter); return m_pUnkOuter; } #if SET_FOO void SetFoo ( IFoo* pFoo ) { m_pUnkOuter = pFoo; } #endif // SET_FOO }; class Baz : public IDitto, public CoClass { public: Baz () { printf ("Baz::Baz(): value of this: 0x%x\n", this ); printf ("Baz::Baz(): value of m_pUnkOuter: 0x%x\n", m_pUnkOuter ); } void Oops () { printf ("Baz::Oops().\n"); } }; int main (int, char **) { printf ("main: Creating CUser object. After successful creation, m_pUnkOuter" " should be a non-null value.\n"); CUser b(0); IFoo* pFoo = &b; printf ("main: Calling IFoo::Bar(). This will end up going through " "m_pUnkOuter.\n"); pFoo->Bar (); printf ("main: If we're here, obviously m_pUnkOuter is non-null...\n"); pFoo = b.GetFoo (); printf ("main: value returned by CoClass::GetFoo(): 0x%x\n", pFoo ); return 0; }