From 8a6538cd6117c5a7b1efb5c2e9cf172a5556c23e Mon Sep 17 00:00:00 2001 From: Sean Silva Date: Thu, 11 Oct 2012 23:30:41 +0000 Subject: docs: Update HowToSetUpLLVMStyleRTTI. Recent changes to isa<>/dyn_cast<> have made unnecessary those classof() of the form: static bool classof(const Foo *) { return true; } Accordingly, remove mention of such classof() from the documentation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165766 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/HowToSetUpLLVMStyleRTTI.rst | 60 ++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 21 deletions(-) (limited to 'docs/HowToSetUpLLVMStyleRTTI.rst') diff --git a/docs/HowToSetUpLLVMStyleRTTI.rst b/docs/HowToSetUpLLVMStyleRTTI.rst index b5c1b78afe..4c96c95a76 100644 --- a/docs/HowToSetUpLLVMStyleRTTI.rst +++ b/docs/HowToSetUpLLVMStyleRTTI.rst @@ -174,8 +174,6 @@ steps: Shape(ShapeKind K) : Kind(K) {} virtual double computeArea() = 0; - + - + static bool classof(const Shape *) { return true; } }; class Square : public Shape { @@ -184,7 +182,6 @@ steps: Square(double S) : Shape(SquareKind), SideLength(S) {} double computeArea() /* override */; + - + static bool classof(const Square *) { return true; } + static bool classof(const Shape *S) { + return S->getKind() == SquareKind; + } @@ -196,31 +193,43 @@ steps: Circle(double R) : Shape(CircleKind), Radius(R) {} double computeArea() /* override */; + - + static bool classof(const Circle *) { return true; } + static bool classof(const Shape *S) { + return S->getKind() == CircleKind; + } }; - Basically, the job of ``classof`` is to return ``true`` if its argument - is of the enclosing class's type. As you can see, there are two general - overloads of ``classof`` in use here. + The job of ``classof`` is to dynamically determine whether an object of + a base class is in fact of a particular derived class. The argument to + ``classof`` should always be an *ancestor* class because the + implementation has logic to allow and optimize away + upcasts/up-``isa<>``'s automatically. It is as though every class + ``Foo`` automatically has a ``classof`` like: + + .. code-block:: c++ + + class Foo { + [...] + static bool classof(const Foo *) { return true; } + [...] + }; + + In order to downcast a type ``Base`` to a type ``Derived``, there needs + to be a ``classof`` in ``Derived`` which will accept an object of type + ``Base``. - #. The first, which just returns ``true``, means that if we know that the - argument of the cast is of the enclosing type *at compile time*, then - we don't need to bother to check anything since we already know that - the type is convertible. This is an optimization for the case that we - statically know the conversion is OK. + To be concrete, in the following code: - #. The other overload takes a pointer to an object of the base of the - class hierarchy: this is the "general case" of the cast. We need to - check the ``Kind`` to dynamically decide if the argument is of (or - derived from) the enclosing type. + .. code-block:: c++ + + Shape *S = ...; + if (isa(S)) { + /* do something ... */ + } - To be more precise, let ``classof`` be inside a class ``C``. Then the - contract for ``classof`` is "return ``true`` if the argument is-a - ``C``". As long as your implementation fulfills this contract, you can - tweak and optimize it as much as you want. + The code of ``isa<>`` will eventually boil down---after template + instantiation and some other machinery---to a check roughly like + ``Circle::classof(S)``. For more information, see + :ref:`classof-contract`. Although for this small example setting up LLVM-style RTTI seems like a lot of "boilerplate", if your classes are doing anything interesting then this @@ -247,7 +256,6 @@ Then in ``Square``, we would need to modify the ``classof`` like so: .. code-block:: c++ - static bool classof(const Square *) { return true; } - static bool classof(const Shape *S) { - return S->getKind() == SquareKind; - } @@ -273,6 +281,16 @@ ordering right:: | OtherSpecialSquare | Circle +.. _classof-contract: + +The Contract of ``classof`` +--------------------------- + +To be more precise, let ``classof`` be inside a class ``C``. Then the +contract for ``classof`` is "return ``true`` if the dynamic type of the +argument is-a ``C``". As long as your implementation fulfills this +contract, you can tweak and optimize it as much as you want. + .. TODO:: Touch on some of the more advanced features, like ``isa_impl`` and -- cgit v1.2.3