Possible to avoid downcasting?
Steven Schveighoffer
schveiguy at gmail.com
Thu Dec 26 17:05:01 UTC 2019
On 12/24/19 2:52 PM, H. S. Teoh wrote:
> I have a function makeTree() that builds a binary tree of BaseNode:
>
> class BaseNode {
> BaseNode* left, right;
> }
> BaseNode makeTree() {
> auto node = new BaseNode(...);
> ...
> return node;
> }
>
> But I want to have the option of creating the tree with derived class
> nodes instead of BaseNode. One option is to pass a factory function to
> makeTree():
>
> BaseNode makeBaseNode() { return new BaseNode(...); }
> BaseNode makeTree(BaseNode function() makeNode = makeBaseNode) {
> auto node = makeNode();
> ...
> return node;
> }
>
> auto tree1 = makeTree(); // tree of BaseNodes
>
> class Derived : BaseNode { ... }
> auto tree2 = makeTree(() => new Derived); // tree of Derived nodes
>
> So far so good. But now I want to iterate over the trees, and I'd like
> to be able to use information in the Derived node directly. But since
> makeTree() returns BaseNode, the only way I can get at the Derived nodes
> is to cast every node to Derived. Furthermore, casting to Derived does
> not change the types of .left and .right, so this cast has to be done
> *every time*.
If you *know* all the types are the same, you can use reinterpret
casting instead of downcasting, which basically will avoid the runtime
checks.
e.g.:
auto realNode = cast(Derived)(cast(void*)node);
Now, aside from that, D does support covariance on virtual functions.
Which can make things more pleasant
So...
class BaseNode
{
BaseNode _left;
BaseNode _right;
BaseNode left() { return _left; }
BaseNode right() { return _right; }
}
class Derived : BaseNode
{
override Derived left() { return cast(Derived)cast(void*)_left; }
override Derived right() { return cast(Derived)cast(void*)_right; }
}
Now, if you know you have a Derived, the left and right properties turn
into Derived as well.
-Steve
More information about the Digitalmars-d
mailing list