#pragma once #include #include #include #include #include #include #include #include "CSingleton.h" class CConversionRegistry : public CSingleton { public: CConversionRegistry() { InitConversions(*this); } void SetTestCommand(const std::string& cmdname) const; template void registerConverter(std::function func) { auto key = std::make_tuple(std::type_index(typeid(From)), std::type_index(typeid(To))); m_converters[key] = [func](const void* from) -> void* { const From* fromPtr = static_cast(from); return new To(func(*fromPtr)); }; } template To convert(const From& from) const { auto key = std::make_tuple(std::type_index(typeid(From)), std::type_index(typeid(To))); auto it = m_converters.find(key); if (it != m_converters.end()) { void* result = it->second(static_cast(&from)); To converted = *static_cast(result); delete static_cast(result); return converted; } throw std::runtime_error("Conversion not registered"); } void* convert(const void* from, const std::type_info& fromType, const std::type_info& toType) const { auto key = std::make_tuple(std::type_index(fromType), std::type_index(toType)); auto it = m_converters.find(key); if (it != m_converters.end()) { return it->second(from); } throw std::runtime_error("Conversion not registered"); } static void InitConversions(CConversionRegistry& registry); private: using ConverterKey = std::tuple; struct ConverterKeyHash { std::size_t operator()(const ConverterKey& key) const { auto hash1 = std::hash()(std::get<0>(key)); auto hash2 = std::hash()(std::get<1>(key)); return hash1 ^ (hash2 << 1); } }; struct ConverterKeyEqual { bool operator()(const ConverterKey& lhs, const ConverterKey& rhs) const { return std::get<0>(lhs) == std::get<0>(rhs) && std::get<1>(lhs) == std::get<1>(rhs); } }; std::unordered_map, ConverterKeyHash, ConverterKeyEqual> m_converters; };