#include #include "ruby.hpp" #include "rice_traits.hpp" #include "Type.hpp" namespace Rice::detail { template inline void TypeRegistry::add() { std::type_index key(typeid(T)); registry_[key] = std::pair(Qnil, nullptr); } template inline void TypeRegistry::add(VALUE klass, rb_data_type_t* rbType) { std::type_index key(typeid(T)); registry_[key] = std::pair(klass, rbType); } template inline void TypeRegistry::remove() { std::type_index key(typeid(T)); registry_.erase(key); } template inline bool TypeRegistry::isDefined() { std::type_index key(typeid(T)); auto iter = registry_.find(key); return iter != registry_.end(); } template inline void TypeRegistry::verifyDefined() { if (!isDefined()) { std::string message = "Type is not defined with Rice: " + detail::typeName(typeid(T)); throw std::invalid_argument(message); } } inline std::optional> TypeRegistry::lookup(const std::type_info& typeInfo) { std::type_index key(typeInfo); auto iter = registry_.find(key); if (iter == registry_.end()) { return std::nullopt; } else { return iter->second; } } template inline std::pair TypeRegistry::figureType(const T& object) { // First check and see if the actual type of the object is registered std::optional> result = lookup(typeid(object)); if (result) { return result.value(); } // If not, then we are willing to accept an ancestor class specified by T. This is needed // to support Directors. Classes inherited from Directors are never actually registered // with Rice - and what we really want it to return the C++ class they inherit from. result = lookup(typeid(T)); if (result) { return result.value(); } // Give up! std::string message = "Type " + typeName(typeid(object)) + " is not registered"; throw std::runtime_error(message.c_str()); } // TODO - hacky to put this here but there is a circular dependency between Type and TypeRegistry template bool Type::verify() { // Use intrinsic_type so that we don't have to define specializations // for pointers, references, const, etc. using Intrinsic_T = intrinsic_type; if constexpr (std::is_fundamental_v) { return true; } else { TypeRegistry::verifyDefined(); return true; } } }