TITLE: the RTTI Visitor pattern


CLARKE: Allan Clarke (clarke@ses.com), 14 Aug 97


Run-time-type-identification refers to identifying an
instance's type at run time. This capability is closely
related to the use of polymorphism; that is, you typically
operate on an instance through a base class pointer.

The current C++ facilities for RTTI are typeid() and
dynamic_cast<>. Using these can sometimes be expensive
in terms of execution time. Also some compilers may not
have implemented these features.

For these reasons, you might consider using an RTTI
Visitor. This construct allows you mimic the use
of dynamic_cast<> without the same drawbacks mentioned
above. Note that the RttiVisitor is a fragile class
in that it violates the Open-Close Principle (see the
tips archive). This tip was inspired by [1].


class RttiVisitor;

class Base
{
  public:
	virtual void visit (RttiVisitor&) = 0;
};

class RttiVisitor
{
  public:
	RttiVisitor () : anA(0), aB(0), aC(0) {}

	void visit (A& a) { anA = &a; }
	void visit (B& b) {  aB = &b; }
	void visit (C& c) {  aC = &c; }

	A* getA () { return anA; }
	B* getB () { return aB;  }
	C* getC () { return aC;  }

  private:
	A* anA;
	B* aB;
	C* aC;
};

A* dynamic_cast_A (Base* b)
{
	RttiVisitor v;
	b->visit (v);
	return v.getA ();
}

B* dynamic_cast_B (Base* b)
{
	RttiVisitor v;
	b->visit (v);
	return v.getB ();
}

C* dynamic_cast_C (Base* b)
{
	RttiVisitor v;
	b->visit (v);
	return v.getC ();
}

class A : public Base
{
  public:
	virtual void visit (RttiVisitor& v) { v.visit (*this); }
};

class B : public Base
{
  public:
	virtual void visit (RttiVisitor& v) { v.visit (*this); }
};

class C : public Base
{
  public:
	virtual void visit (RttiVisitor& v) { v.visit (*this); }
};


A finally the client code looks like

	Base* bp = foobar ();
	...
	A* ap = dynamic_cast_A (bp);
	...


[1] Martin, Robert C. "Design Patterns for Dealing with
    Dual Inheritance Heirarchies in C++", C++ Report,
    April 1997.


