mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
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. llvm-svn: 165766
This commit is contained in:
parent
356281d8ad
commit
d3a75e9f68
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user