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
This commit is contained in:
Sean Silva 2012-10-11 23:30:41 +00:00
parent 8b8fa7b2f4
commit 8a6538cd61

View File

@ -174,8 +174,6 @@ steps:
Shape(ShapeKind K) : Kind(K) {} Shape(ShapeKind K) : Kind(K) {}
virtual double computeArea() = 0; virtual double computeArea() = 0;
+
+ static bool classof(const Shape *) { return true; }
}; };
class Square : public Shape { class Square : public Shape {
@ -184,7 +182,6 @@ steps:
Square(double S) : Shape(SquareKind), SideLength(S) {} Square(double S) : Shape(SquareKind), SideLength(S) {}
double computeArea() /* override */; double computeArea() /* override */;
+ +
+ static bool classof(const Square *) { return true; }
+ static bool classof(const Shape *S) { + static bool classof(const Shape *S) {
+ return S->getKind() == SquareKind; + return S->getKind() == SquareKind;
+ } + }
@ -196,31 +193,43 @@ steps:
Circle(double R) : Shape(CircleKind), Radius(R) {} Circle(double R) : Shape(CircleKind), Radius(R) {}
double computeArea() /* override */; double computeArea() /* override */;
+ +
+ static bool classof(const Circle *) { return true; }
+ static bool classof(const Shape *S) { + static bool classof(const Shape *S) {
+ return S->getKind() == CircleKind; + return S->getKind() == CircleKind;
+ } + }
}; };
Basically, the job of ``classof`` is to return ``true`` if its argument The job of ``classof`` is to dynamically determine whether an object of
is of the enclosing class's type. As you can see, there are two general a base class is in fact of a particular derived class. The argument to
overloads of ``classof`` in use here. ``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:
#. The first, which just returns ``true``, means that if we know that the .. code-block:: c++
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.
#. The other overload takes a pointer to an object of the base of the class Foo {
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 static bool classof(const Foo *) { return true; }
derived from) the enclosing type. [...]
};
To be more precise, let ``classof`` be inside a class ``C``. Then the In order to downcast a type ``Base`` to a type ``Derived``, there needs
contract for ``classof`` is "return ``true`` if the argument is-a to be a ``classof`` in ``Derived`` which will accept an object of type
``C``". As long as your implementation fulfills this contract, you can ``Base``.
tweak and optimize it as much as you want.
To be concrete, in the following code:
.. code-block:: c++
Shape *S = ...;
if (isa<Circle>(S)) {
/* do something ... */
}
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 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 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++ .. code-block:: c++
static bool classof(const Square *) { return true; }
- static bool classof(const Shape *S) { - static bool classof(const Shape *S) {
- return S->getKind() == SquareKind; - return S->getKind() == SquareKind;
- } - }
@ -273,6 +281,16 @@ ordering right::
| OtherSpecialSquare | OtherSpecialSquare
| Circle | 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:: .. TODO::
Touch on some of the more advanced features, like ``isa_impl`` and Touch on some of the more advanced features, like ``isa_impl`` and