LLVM’s RTTI Replacement
LLVM 禁止使用 C++ native RTTI,主要是嫌弃 native RTTI 的 performance,并不是说 LLVM 不需要 RTTI 这个 feature。我们可以说 LLVM 自己实现了一套新的 RTTI (以下称 LLVM-style RTTI),它有:
llvm::isa<>
: something like Javainstanceof
llvm::cast<>
: if it fails, it will abort the program. Use it only when you’re super confident about the castingllvm::cast_if_present
: a variant ofllvm::cast<>
, but acceptsnullptr
llvm::dyn_cast<>
: something likedynamic_cast
llvm::dyn_cast_if_present
: a variant ofllvm::dyn_cast<>
, but acceptsnullptr
我们通过 llvm::isa<>
来探查一下 LLVM-style RTTI 到底是怎么实现的,它的设计如下:
class Animal { // 基类
public:
enum AnimalKind { AK_Horse, AK_Sheep }
public:
Animal(AnimalKind ak) : kind(ak) {};
AnimalKind getKind() const { return kind; }
private:
const AnimalKind kind;
};
class Horse : public Animal { // 子类 #1
public:
Horse() : Animal(AK_Horse) {};
static bool classof(const Animal *a) { return a->getKind() == AK_Horse; }
};
class Sheep : public Animal { // 子类 #2
public:
Sheep() : Animal(AK_Sheep) {}
static bool classof(const Animal *a) { return a->getKind() == AK_Sheep; }
}
template <typename To, typename From>
bool isa(const From *from) {
// `isa<To>(From *from)` checks if `from` is of class `To`
// works like `from instanceof To`
return To::classof(from);
}
auto animal_ptr = std::make_unique<Horse>();
isa<Horse>(animal_ptr); // return true
isa<Sheep>(animal_ptr); // return false
这个设计的优点:
- 使用了 class tags (i.e.
enum AnimalKind
) 来判断instaceof
,性能上比 traversal through inheritance hierarchy 要好- 这个性能上的优势在 inheritance hierarchy 很深的时候尤其明显,在例子中这个很浅的 hierarchy 中可能不显著
缺点也是有的:
- 严格的 protocol:
- 所有的基类都要定义 class tags 全集
- 每个子类都要有一个 class tag
- 每个子类都要实现
classof
classof
中a->getKind()
这句只能 dynamic binding,performance 上算是一点 overhead- 可读性欠佳:
isa
那个 template 还是有点绕- 名字也不如
instanceof
好懂
参考:
- Section 4.3.1 RTTI replacement and cast operators, Clang Compiler Frontend by Ivan Murashko
- How to set up LLVM-style RTTI for your class hierarchy
Comments