I am using the visitor pattern to deal with a lot of different AST problems, which turns out to work really well. For instance, I am using it to check for static type. This works well when looking for the exact type, however it doesn't apply to derived classes. i.e. If we have Derived
that inherit from Base
, asking if a Derived
object is a Base
fails.
Consider the following C++ code:
#include <iostream>
#include <functional>
#include <memory>
using namespace std;
class Base;
class Derived;
class Visitor {
public:
virtual void visit(Base& object) = 0;
virtual void visit(Derived& object) = 0;
};
class EmptyVisitor : public Visitor {
public:
virtual void visit(Base& object) override {}
virtual void visit(Derived& object) override {}
};
template <class TYPE> class LogicVisitor : public EmptyVisitor {
public:
LogicVisitor(function<void(TYPE&)> logic) : EmptyVisitor(), logic(logic) {}
virtual void visit(TYPE& object) override { logic(object); }
private:
function<void(TYPE&)> logic;
};
class Base {
public:
virtual void accept(Visitor* visitor) {
visitor->visit(*this);
}
};
class Derived : public Base {
public:
virtual void accept(Visitor* visitor) override {
visitor->visit(*this);
}
};
template <class TYPE> bool is_type(shared_ptr<Base> base)
{
bool is_type = false;
LogicVisitor<TYPE> logic_visitor([&](TYPE& object) {
is_type = true;
});
base->accept((Visitor*)&logic_visitor);
return is_type;
}
int main() {
auto base = make_shared<Base>();
auto derived = make_shared<Derived>();
cout << "is_type<Base>(base) = " << (is_type<Base>(base) ? "true" : "false") << endl;
cout << "is_type<Derived>(base) = " << (is_type<Derived>(base) ? "true" : "false") << endl;
cout << "is_type<Base>(derived) = " << (is_type<Base>(derived) ? "true" : "false") << endl;
cout << "is_type<Derived>(derived) = " << (is_type<Derived>(derived) ? "true" : "false") << endl;
return 0;
}
It outputs as expected the following result:
is_type<Base>(base) = true
is_type<Derived>(base) = false
is_type<Base>(derived) = false
is_type<Derived>(derived) = true
While this is great to retrieve the static type of an object, how can this be fixed if I wanted is_type<Base>(derived)
to return true
instead of false
so that I can effectively check class inheritance? Is this possible in C++?
std::is_base_of
?std::is_base_of
, that looks very useful indeed, but then the question is, does this function require RTTI?