Question

LLVM has it's own hand rolled alternative to RTTI that is a speed improvement over built-in RTTI and allows dynamic casting to classes with no vtable (dyn_cast). However, it can still be used in exactly the way that dynamic_cast<> is used though it does allow it to be used with more classes.

dyn_cast<> template documentation

LLVM is a reputable C++ project so this seems to fly in the face of the common saying that too many dynamic casts is a sign of bad design, also known as a code smell. Surely a better performing dynamic cast does nothing to improve its use in design than a standard dynamic_cast. So who is right here? Are there cases where large-scale use of dynamic casting is a good design choice in C++ code? Google turns up 690 occurrences of this kind of dynamic casting in the LLVM trunk source code.

Uses of dyn_cast<> in LLVM trunk

Was it helpful?

Solution

While performance hits are a reason to avoid dynamic_cast<> for large class hierarchies, it's not the only reason you might want to avoid them. Better performing or not, one should not be more encouraged to use dyn_cast<> because of this claim.

On the other hand, there's absolutely nothing wrong with using dynamic_cast<> when it's the best tool for the job. If its use is justified, and the cleanest way to solve a problem, then it's always right, regardless of the "common saying".

I would certainly not steer clear of popular projects simply because they use dynamic_cast<>s, gotos or any other idiom that's fallen out of favour.

OTHER TIPS

I think dynamics casts are bad not because they are slow, but because they imply that your code is too tightly coupled.

I've only taken a very quick look at the implementation of dyn_cast and isa in the LLVM documentation.

The exmaple in the code has the following:

struct bar {
  bar() {}
private:
  bar(const bar &);

};
struct foo {
  void ext() const;
  /*  static bool classof(const bar *X) {
    cerr << "Classof: " << X << "\n";
    return true;
    }*/
};

template <> inline bool isa_impl<foo,bar>(const bar &Val) {
  errs() << "Classof: " << &Val << "\n";
  return true;
}

The test is called with a B and has:

if (!isa<foo>(B1)) return;
if (!isa<foo>(B2)) return;

If I understand what's going on correctly, the isa template (which is used by dyn_cast) uses the explicit specialization of isa_impl to link bar with foo. In the examples given it seems that isa<foo>(B1) returns true!

Anyway, this is very different behaviour to that of dynamic_cast, so I really don't think you can compare them against each other.

Obviously, I may be mis-understanding what LLVM is doing, so please let me know if I've not understood the code!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top