While C++'s built-in RTTI system is not directly extensible, it's possible to build a custom reflection system that works alongside RTTI for user-defined types.
This approach allows you to create a more powerful and flexible type information system tailored to your specific needs.
Here's an example of how you might implement a basic custom reflection system. First, define a base class for reflectable types:
#include <string>
class Reflectable {
public:
virtual ~Reflectable() = default;
virtual std::string getTypeName() const = 0;
};
Create a reflection registry:
#include <string>
#include <typeinfo>
#include <unordered_map>
class Reflectable {/*...*/};
class ReflectionRegistry {
public:
template <typename T>
void registerType(const std::string& name) {
typeMap_[typeid(T).name()] = name;
}
std::string getTypeName(
const std::type_info& info
) const {
auto it = typeMap_.find(info.name());
return (it != typeMap_.end())
? it->second
: "Unknown";
}
private:
std::unordered_map<std::string, std::string>
typeMap_;
};
ReflectionRegistry& getRegistry() {
static ReflectionRegistry registry;
return registry;
}
Implement reflectable types:
#include <string>
#include <typeinfo>
#include <unordered_map>
class Reflectable {/*...*/};
class ReflectionRegistry {/*...*/};
class Monster : public Reflectable {
public:
std::string getTypeName() const override {
return getRegistry().getTypeName(
typeid(*this)
);
}
};
class Dragon : public Monster {
// Dragon-specific implementation
};
inline void registerTypes() {
getRegistry().registerType<Monster>("Monster");
getRegistry().registerType<Dragon>("Dragon");
}
Use the custom reflection system:
#include <iostream>
#include <memory>
#include <string>
#include <typeinfo>
#include <unordered_map>
class Reflectable {/*...*/};
class ReflectionRegistry {/*...*/};
class Monster : public Reflectable {/*...*/};
class Dragon : public Monster {/*...*/};
inline void registerTypes() {/*...*/}
int main() {
registerTypes();
std::unique_ptr<Monster> monster =
std::make_unique<Monster>();
std::unique_ptr<Monster> dragon =
std::make_unique<Dragon>();
std::cout << "Monster type: "
<< monster->getTypeName() << '\n';
std::cout << "Dragon type: "
<< dragon->getTypeName() << '\n';
// You can still use standard RTTI alongside
// your custom system
std::cout << "Is dragon a Dragon? "
<< (typeid(*dragon) == typeid(Dragon)
? "Yes" : "No");
}
Monster type: Monster
Dragon type: Dragon
Is dragon a Dragon? Yes
This custom reflection system allows you to:
You could further enhance this system by adding features like:
Remember that while this custom system provides more flexibility, it also requires more maintenance and may have a higher performance cost than built-in RTTI. Always consider the trade-offs for your specific use case.
Answers to questions are automatically generated and may not have been reviewed.
typeid()
Learn to identify and react to object types at runtime using RTTI, dynamic casting and the typeid()
operator