浏览代码

Simplified CTypeList class

Ivan Savenko 1 年之前
父节点
当前提交
4a7fa9bf8c

+ 2 - 2
AI/Nullkiller/AIGateway.cpp

@@ -421,14 +421,14 @@ void AIGateway::requestRealized(PackageApplied * pa)
 	NET_EVENT_HANDLER;
 	if(status.haveTurn())
 	{
-		if(pa->packType == typeList.getTypeID<EndTurn>())
+		if(pa->packType == CTypeList::getInstance().getTypeID<EndTurn>(nullptr))
 		{
 			if(pa->result)
 				status.madeTurn();
 		}
 	}
 
-	if(pa->packType == typeList.getTypeID<QueryReply>())
+	if(pa->packType == CTypeList::getInstance().getTypeID<QueryReply>(nullptr))
 	{
 		status.receivedAnswerConfirmation(pa->requestID, pa->result);
 	}

+ 2 - 2
AI/VCAI/VCAI.cpp

@@ -505,14 +505,14 @@ void VCAI::requestRealized(PackageApplied * pa)
 	NET_EVENT_HANDLER;
 	if(status.haveTurn())
 	{
-		if(pa->packType == typeList.getTypeID<EndTurn>())
+		if(pa->packType == CTypeList::getInstance().getTypeID<EndTurn>(nullptr))
 		{
 			if(pa->result)
 				status.madeTurn();
 		}
 	}
 
-	if(pa->packType == typeList.getTypeID<QueryReply>())
+	if(pa->packType == CTypeList::getInstance().getTypeID<QueryReply>(nullptr))
 	{
 		status.receivedAnswerConfirmation(pa->requestID, pa->result);
 	}

+ 2 - 2
client/CPlayerInterface.cpp

@@ -1243,10 +1243,10 @@ void CPlayerInterface::showArtifactAssemblyDialog(const Artifact * artifact, con
 
 void CPlayerInterface::requestRealized( PackageApplied *pa )
 {
-	if(pa->packType == typeList.getTypeID<MoveHero>())
+	if(pa->packType == CTypeList::getInstance().getTypeID<MoveHero>(nullptr))
 		movementController->onMoveHeroApplied();
 
-	if(pa->packType == typeList.getTypeID<QueryReply>())
+	if(pa->packType == CTypeList::getInstance().getTypeID<QueryReply>(nullptr))
 		movementController->onQueryReplyApplied();
 }
 

+ 4 - 4
client/CServerHandler.cpp

@@ -94,7 +94,7 @@ public:
 		T * ptr = static_cast<T *>(pack);
 		ApplyOnLobbyHandlerNetPackVisitor visitor(*handler);
 
-		logNetwork->trace("\tImmediately apply on lobby: %s", typeList.getTypeInfo(ptr)->name());
+		logNetwork->trace("\tImmediately apply on lobby: %s", typeid(ptr).name());
 		ptr->visit(visitor);
 
 		return visitor.getResult();
@@ -105,7 +105,7 @@ public:
 		T * ptr = static_cast<T *>(pack);
 		ApplyOnLobbyScreenNetPackVisitor visitor(*handler, lobby);
 
-		logNetwork->trace("\tApply on lobby from queue: %s", typeList.getTypeInfo(ptr)->name());
+		logNetwork->trace("\tApply on lobby from queue: %s", typeid(ptr).name());
 		ptr->visit(visitor);
 	}
 };
@@ -298,7 +298,7 @@ void CServerHandler::applyPacksOnLobbyScreen()
 		boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
 		CPackForLobby * pack = packsForLobbyScreen.front();
 		packsForLobbyScreen.pop_front();
-		CBaseForLobbyApply * apply = applier->getApplier(typeList.getTypeID(pack)); //find the applier
+		CBaseForLobbyApply * apply = applier->getApplier(CTypeList::getInstance().getTypeID(pack)); //find the applier
 		apply->applyOnLobbyScreen(dynamic_cast<CLobbyScreen *>(SEL), this, pack);
 		GH.windows().totalRedraw();
 		delete pack;
@@ -953,7 +953,7 @@ void CServerHandler::threadHandleConnection()
 
 void CServerHandler::visitForLobby(CPackForLobby & lobbyPack)
 {
-	if(applier->getApplier(typeList.getTypeID(&lobbyPack))->applyOnLobbyHandler(this, &lobbyPack))
+	if(applier->getApplier(CTypeList::getInstance().getTypeID(&lobbyPack))->applyOnLobbyHandler(this, &lobbyPack))
 	{
 		if(!settings["session"]["headless"].Bool())
 		{

+ 5 - 5
client/Client.cpp

@@ -523,20 +523,20 @@ void CClient::installNewBattleInterface(std::shared_ptr<CBattleGameInterface> ba
 
 void CClient::handlePack(CPack * pack)
 {
-	CBaseForCLApply * apply = applier->getApplier(typeList.getTypeID(pack)); //find the applier
+	CBaseForCLApply * apply = applier->getApplier(CTypeList::getInstance().getTypeID(pack)); //find the applier
 	if(apply)
 	{
 		boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
 		apply->applyOnClBefore(this, pack);
-		logNetwork->trace("\tMade first apply on cl: %s", typeList.getTypeInfo(pack)->name());
+		logNetwork->trace("\tMade first apply on cl: %s", typeid(pack).name());
 		gs->apply(pack);
-		logNetwork->trace("\tApplied on gs: %s", typeList.getTypeInfo(pack)->name());
+		logNetwork->trace("\tApplied on gs: %s", typeid(pack).name());
 		apply->applyOnClAfter(this, pack);
-		logNetwork->trace("\tMade second apply on cl: %s", typeList.getTypeInfo(pack)->name());
+		logNetwork->trace("\tMade second apply on cl: %s", typeid(pack).name());
 	}
 	else
 	{
-		logNetwork->error("Message %s cannot be applied, cannot find applier!", typeList.getTypeInfo(pack)->name());
+		logNetwork->error("Message %s cannot be applied, cannot find applier!", typeid(pack).name());
 	}
 	delete pack;
 }

+ 1 - 1
lib/gameState/CGameState.cpp

@@ -1134,7 +1134,7 @@ PlayerRelations CGameState::getPlayerRelations( PlayerColor color1, PlayerColor
 
 void CGameState::apply(CPack *pack)
 {
-	ui16 typ = typeList.getTypeID(pack);
+	ui16 typ = CTypeList::getInstance().getTypeID(pack);
 	applier->getApplier(typ)->applyOnGS(this, pack);
 }
 

+ 1 - 2
lib/registerTypes/RegisterTypes.cpp

@@ -34,8 +34,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 
 #define DEFINE_EXTERNAL_METHOD(METHODNAME) \
 extern template DLL_LINKAGE void METHODNAME<BinaryDeserializer>(BinaryDeserializer & s); \
-extern template DLL_LINKAGE void METHODNAME<BinarySerializer>(BinarySerializer & s); \
-extern template DLL_LINKAGE void METHODNAME<CTypeList>(CTypeList & s); \
+extern template DLL_LINKAGE void METHODNAME<BinarySerializer>(BinarySerializer & s);
 
 //DEFINE_EXTERNAL_METHOD(registerTypesMapObjects)
 DEFINE_EXTERNAL_METHOD(registerTypesMapObjects1)

+ 1 - 1
lib/registerTypes/RegisterTypes.h

@@ -19,6 +19,7 @@
 #include "../mapObjects/CGCreature.h"
 #include "../mapObjects/CGTownBuilding.h"
 #include "../mapObjects/ObjectTemplate.h"
+#include "../battle/BattleInfo.h"
 #include "../battle/CObstacleInstance.h"
 #include "../bonuses/Limiters.h"
 #include "../bonuses/Updaters.h"
@@ -351,7 +352,6 @@ void registerTypes(Serializer &s)
 
 extern template DLL_LINKAGE void registerTypes<BinaryDeserializer>(BinaryDeserializer & s);
 extern template DLL_LINKAGE void registerTypes<BinarySerializer>(BinarySerializer & s);
-extern template DLL_LINKAGE void registerTypes<CTypeList>(CTypeList & s);
 
 #endif
 

+ 20 - 43
lib/serializer/BinaryDeserializer.h

@@ -9,6 +9,7 @@
  */
 #pragma once
 
+#include "CSerializer.h"
 #include "CTypeList.h"
 #include "../mapObjects/CGHeroInstance.h"
 #include "../../Global.h"
@@ -100,40 +101,39 @@ class DLL_LINKAGE BinaryDeserializer : public CLoaderBase
 		return length;
 	}
 
-	template <typename T> class CPointerLoader;
+	template <typename Type> class CPointerLoader;
 
-	class CBasicPointerLoader
+	class IPointerLoader
 	{
 	public:
-		virtual const std::type_info * loadPtr(CLoaderBase &ar, void *data, ui32 pid) const =0; //data is pointer to the ACTUAL POINTER
-		virtual ~CBasicPointerLoader(){}
+		virtual void * loadPtr(CLoaderBase &ar, ui32 pid) const =0; //data is pointer to the ACTUAL POINTER
+		virtual ~IPointerLoader() = default;
 
-		template<typename T> static CBasicPointerLoader *getApplier(const T * t=nullptr)
+		template<typename Type> static IPointerLoader *getApplier(const Type * t = nullptr)
 		{
-			return new CPointerLoader<T>();
+			return new CPointerLoader<Type>();
 		}
 	};
 
-	template <typename T> class CPointerLoader : public CBasicPointerLoader
+	template <typename Type> class CPointerLoader : public IPointerLoader
 	{
 	public:
-		const std::type_info * loadPtr(CLoaderBase &ar, void *data, ui32 pid) const override //data is pointer to the ACTUAL POINTER
+		void * loadPtr(CLoaderBase &ar, ui32 pid) const override //data is pointer to the ACTUAL POINTER
 		{
 			auto & s = static_cast<BinaryDeserializer &>(ar);
-			T *&ptr = *static_cast<T**>(data);
 
 			//create new object under pointer
-			typedef typename std::remove_pointer<T>::type npT;
-			ptr = ClassObjectCreator<npT>::invoke(); //does new npT or throws for abstract classes
+			Type * ptr = ClassObjectCreator<Type>::invoke(); //does new npT or throws for abstract classes
 			s.ptrAllocated(ptr, pid);
-			//T is most derived known type, it's time to call actual serialize
+
 			assert(s.fileVersion != 0);
 			ptr->serialize(s,s.fileVersion);
-			return &typeid(T);
+
+			return static_cast<void*>(ptr);
 		}
 	};
 
-	CApplier<CBasicPointerLoader> applier;
+	CApplier<IPointerLoader> applier;
 
 	int write(const void * data, unsigned size);
 
@@ -143,7 +143,7 @@ public:
 
 	std::map<ui32, void*> loadedPointers;
 	std::map<ui32, const std::type_info*> loadedPointersTypes;
-	std::map<const void*, std::any> loadedSharedPointers;
+	std::map<const void*, std::shared_ptr<void>> loadedSharedPointers;
 	bool smartPointerSerialization;
 	bool saving;
 
@@ -288,7 +288,7 @@ public:
 				// We already got this pointer
 				// Cast it in case we are loading it to a non-first base pointer
 				assert(loadedPointersTypes.count(pid));
-				data = reinterpret_cast<T>(typeList.castRaw(i->second, loadedPointersTypes.at(pid), &typeid(typename std::remove_const<typename std::remove_pointer<T>::type>::type)));
+				data = static_cast<T>(i->second);
 				return;
 			}
 		}
@@ -313,8 +313,7 @@ public:
 				data = nullptr;
 				return;
 			}
-			auto typeInfo = app->loadPtr(*this,&data, pid);
-			data = reinterpret_cast<T>(typeList.castRaw((void*)data, typeInfo, &typeid(typename std::remove_const<typename std::remove_pointer<T>::type>::type)));
+			data = static_cast<T>(app->loadPtr(*this, pid));
 		}
 	}
 
@@ -340,7 +339,7 @@ public:
 		NonConstT *internalPtr;
 		load(internalPtr);
 
-		void *internalPtrDerived = typeList.castToMostDerived(internalPtr);
+		void * internalPtrDerived = static_cast<void*>(internalPtr);
 
 		if(internalPtr)
 		{
@@ -349,35 +348,13 @@ public:
 			{
 				// This pointers is already loaded. The "data" needs to be pointed to it,
 				// so their shared state is actually shared.
-				try
-				{
-					auto actualType = typeList.getTypeInfo(internalPtr);
-					auto typeWeNeedToReturn = typeList.getTypeInfo<T>();
-					if(*actualType == *typeWeNeedToReturn)
-					{
-						// No casting needed, just unpack already stored shared_ptr and return it
-						data = std::any_cast<std::shared_ptr<T>>(itr->second);
-					}
-					else
-					{
-						// We need to perform series of casts
-						auto ret = typeList.castShared(itr->second, actualType, typeWeNeedToReturn);
-						data = std::any_cast<std::shared_ptr<T>>(ret);
-					}
-				}
-				catch(std::exception &e)
-				{
-					logGlobal->error(e.what());
-					logGlobal->error("Failed to cast stored shared ptr. Real type: %s. Needed type %s. FIXME FIXME FIXME", itr->second.type().name(), typeid(std::shared_ptr<T>).name());
-					//TODO scenario with inheritance -> we can have stored ptr to base and load ptr to derived (or vice versa)
-					throw;
-				}
+				data = std::static_pointer_cast<T>(itr->second);
 			}
 			else
 			{
 				auto hlp = std::shared_ptr<NonConstT>(internalPtr);
 				data = hlp;
-				loadedSharedPointers[internalPtrDerived] = typeList.castSharedToMostDerived(hlp);
+				loadedSharedPointers[internalPtrDerived] = std::static_pointer_cast<void>(hlp);
 			}
 		}
 		else

+ 6 - 4
lib/serializer/BinarySerializer.h

@@ -9,6 +9,7 @@
  */
 #pragma once
 
+#include "CSerializer.h"
 #include "CTypeList.h"
 #include "../mapObjects/CArmedInstance.h"
 
@@ -194,9 +195,10 @@ public:
 	template < typename T, typename std::enable_if < !std::is_base_of_v<Entity, std::remove_pointer_t<T>>, int  >::type = 0 >
 	void savePointerImpl(const T &data)
 	{
+		typedef typename std::remove_const<typename std::remove_pointer<T>::type>::type TObjectType;
+
 		if(writer->smartVectorMembersSerialization)
 		{
-			typedef typename std::remove_const<typename std::remove_pointer<T>::type>::type TObjectType;
 			typedef typename VectorizedTypeFor<TObjectType>::type VType;
 			typedef typename VectorizedIDType<TObjectType>::type IDType;
 
@@ -220,7 +222,7 @@ public:
 		{
 			// We might have an object that has multiple inheritance and store it via the non-first base pointer.
 			// Therefore, all pointers need to be normalized to the actual object address.
-			auto actualPointer = typeList.castToMostDerived(data);
+			const void * actualPointer = static_cast<const void*>(data);
 			auto i = savedPointers.find(actualPointer);
 			if(i != savedPointers.end())
 			{
@@ -236,13 +238,13 @@ public:
 		}
 
 		//write type identifier
-		ui16 tid = typeList.getTypeID(data);
+		uint16_t tid = CTypeList::getInstance().getTypeID(data);
 		save(tid);
 
 		if(!tid)
 			save(*data); //if type is unregistered simply write all data in a standard way
 		else
-			applier.getApplier(tid)->savePtr(*this, typeList.castToMostDerived(data));  //call serializer specific for our real type
+			applier.getApplier(tid)->savePtr(*this, static_cast<const void*>(data));  //call serializer specific for our real type
 	}
 
 	template < typename T, typename std::enable_if < is_serializeable<BinarySerializer, T>::value, int  >::type = 0 >

+ 0 - 119
lib/serializer/CTypeList.cpp

@@ -14,128 +14,9 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-extern template void registerTypes<CTypeList>(CTypeList & s);
-
-CTypeList typeList;
-
 CTypeList::CTypeList()
 {
 	registerTypes(*this);
 }
 
-CTypeList::TypeInfoPtr CTypeList::registerType(const std::type_info *type)
-{
-	if(auto typeDescr = getTypeDescriptor(type, false))
-		return typeDescr;  //type found, return ptr to structure
-
-	//type not found - add it to the list and return given ID
-	auto newType = std::make_shared<TypeDescriptor>();
-	newType->typeID = static_cast<ui16>(typeInfos.size() + 1);
-	newType->name = type->name();
-	typeInfos[type] = newType;
-
-	return newType;
-}
-
-ui16 CTypeList::getTypeID(const std::type_info *type, bool throws) const
-{
-	auto descriptor = getTypeDescriptor(type, throws);
-	if (descriptor == nullptr)
-	{
-		return 0;
-	}
-	return descriptor->typeID;
-}
-
-CTypeList::TypeInfoPtr CTypeList::getTypeDescriptor(ui16 typeID) const
-{
-	auto found = std::find_if(typeInfos.begin(), typeInfos.end(), [typeID](const std::pair<const std::type_info *, TypeInfoPtr> & p) -> bool
-		{
-			return p.second->typeID == typeID;
-		});
-
-	if(found != typeInfos.end())
-	{
-		return found->second;
-	}
-
-	return TypeInfoPtr();
-}
-
-std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(TypeInfoPtr from, TypeInfoPtr to) const
-{
-	if(!strcmp(from->name, to->name))
-		return std::vector<CTypeList::TypeInfoPtr>();
-
-	// Perform a simple BFS in the class hierarchy.
-
-	auto BFS = [&](bool upcast)
-	{
-		std::map<TypeInfoPtr, TypeInfoPtr> previous;
-		std::queue<TypeInfoPtr> q;
-		q.push(to);
-		while(!q.empty())
-		{
-			auto typeNode = q.front();
-			q.pop();
-			for(auto & weakNode : (upcast ? typeNode->parents : typeNode->children) )
-			{
-				auto nodeBase = weakNode.lock();
-				if(!previous.count(nodeBase))
-				{
-					previous[nodeBase] = typeNode;
-					q.push(nodeBase);
-				}
-			}
-		}
-
-		std::vector<TypeInfoPtr> ret;
-
-		if(!previous.count(from))
-			return ret;
-
-		ret.push_back(from);
-		TypeInfoPtr ptr = from;
-		do
-		{
-			ptr = previous.at(ptr);
-			ret.push_back(ptr);
-		} while(ptr != to);
-
-		return ret;
-	};
-
-	// Try looking both up and down.
-	auto ret = BFS(true);
-	if(ret.empty())
-		ret = BFS(false);
-
-	if(ret.empty())
-		THROW_FORMAT("Cannot find relation between types %s and %s. Were they (and all classes between them) properly registered?", from->name % to->name);
-
-	return ret;
-}
-
-std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(const std::type_info *from, const std::type_info *to) const
-{
-	//This additional if is needed because getTypeDescriptor might fail if type is not registered
-	// (and if casting is not needed, then registereing should no  be required)
-	if(!strcmp(from->name(), to->name()))
-		return std::vector<CTypeList::TypeInfoPtr>();
-
-	return castSequence(getTypeDescriptor(from), getTypeDescriptor(to));
-}
-
-CTypeList::TypeInfoPtr CTypeList::getTypeDescriptor(const std::type_info *type, bool throws) const
-{
-	auto i = typeInfos.find(type);
-	if(i != typeInfos.end())
-		return i->second; //type found, return ptr to structure
-
-	if(!throws)
-		return nullptr;
-
-	THROW_FORMAT("Cannot find type descriptor for type %s. Was it registered?", type->name());
-}
-
 VCMI_LIB_NAMESPACE_END

+ 34 - 162
lib/serializer/CTypeList.h

@@ -9,199 +9,72 @@
  */
 #pragma once
 
-#include "CSerializer.h"
-
 VCMI_LIB_NAMESPACE_BEGIN
 
-struct IPointerCaster
-{
-	virtual std::any castRawPtr(const std::any &ptr) const = 0; // takes From*, returns To*
-	virtual std::any castSharedPtr(const std::any &ptr) const = 0; // takes std::shared_ptr<From>, performs dynamic cast, returns std::shared_ptr<To>
-	virtual std::any castWeakPtr(const std::any &ptr) const = 0; // takes std::weak_ptr<From>, performs dynamic cast, returns std::weak_ptr<To>. The object under poitner must live.
-	//virtual std::any castUniquePtr(const std::any &ptr) const = 0; // takes std::unique_ptr<From>, performs dynamic cast, returns std::unique_ptr<To>
-	virtual ~IPointerCaster() = default;
-};
-
-template <typename From, typename To>
-struct PointerCaster : IPointerCaster
-{
-	virtual std::any castRawPtr(const std::any &ptr) const override // takes void* pointing to From object, performs dynamic cast, returns void* pointing to To object
-	{
-		From * from = (From*)std::any_cast<void*>(ptr);
-		To * ret = static_cast<To*>(from);
-		return (void*)ret;
-	}
-
-	// Helper function performing casts between smart pointers
-	template<typename SmartPt>
-	std::any castSmartPtr(const std::any &ptr) const
-	{
-		try
-		{
-			auto from = std::any_cast<SmartPt>(ptr);
-			auto ret = std::static_pointer_cast<To>(from);
-			return ret;
-		}
-		catch(std::exception &e)
-		{
-			THROW_FORMAT("Failed cast %s -> %s. Given argument was %s. Error message: %s", typeid(From).name() % typeid(To).name() % ptr.type().name() % e.what());
-		}
-	}
-
-	virtual std::any castSharedPtr(const std::any &ptr) const override
-	{
-		return castSmartPtr<std::shared_ptr<From>>(ptr);
-	}
-	virtual std::any castWeakPtr(const std::any &ptr) const override
-	{
-		auto from = std::any_cast<std::weak_ptr<From>>(ptr);
-		return castSmartPtr<std::shared_ptr<From>>(from.lock());
-	}
-};
-
 /// Class that implements basic reflection-like mechanisms
 /// For every type registered via registerType() generates inheritance tree
 /// Rarely used directly - usually used as part of CApplier
-class DLL_LINKAGE CTypeList: public boost::noncopyable
+class CTypeList
 {
-//public:
-	struct TypeDescriptor;
-	using TypeInfoPtr = std::shared_ptr<TypeDescriptor>;
-	using WeakTypeInfoPtr = std::weak_ptr<TypeDescriptor>;
-	struct TypeDescriptor
-	{
-		ui16 typeID;
-		const char *name;
-		std::vector<WeakTypeInfoPtr> children, parents;
-	};
-	using TMutex = boost::shared_mutex;
-	using TUniqueLock = boost::unique_lock<TMutex>;
-	using TSharedLock = boost::shared_lock<TMutex>;
-
-private:
-	mutable TMutex mx;
-
-	std::map<const std::type_info *, TypeInfoPtr, TypeComparer> typeInfos;
-	std::map<std::pair<TypeInfoPtr, TypeInfoPtr>, std::unique_ptr<const IPointerCaster>> casters; //for each pair <Base, Der> we provide a caster (each registered relations creates a single entry here)
-
-	/// Returns sequence of types starting from "from" and ending on "to". Every next type is derived from the previous.
-	/// Throws if there is no link registered.
-	std::vector<TypeInfoPtr> castSequence(TypeInfoPtr from, TypeInfoPtr to) const;
-	std::vector<TypeInfoPtr> castSequence(const std::type_info *from, const std::type_info *to) const;
-
-	template<std::any(IPointerCaster::*CastingFunction)(const std::any &) const>
-	std::any castHelper(std::any inputPtr, const std::type_info *fromArg, const std::type_info *toArg) const
-	{
-		TSharedLock lock(mx);
-		auto typesSequence = castSequence(fromArg, toArg);
+	std::map<std::string, uint16_t> typeInfos;
 
-		std::any ptr = inputPtr;
-		for(int i = 0; i < static_cast<int>(typesSequence.size()) - 1; i++)
-		{
-			auto &from = typesSequence[i];
-			auto &to = typesSequence[i + 1];
-			auto castingPair = std::make_pair(from, to);
-			if(!casters.count(castingPair))
-				THROW_FORMAT("Cannot find caster for conversion %s -> %s which is needed to cast %s -> %s", from->name % to->name % fromArg->name() % toArg->name());
-
-			const auto & caster = casters.at(castingPair);
-			ptr = (*caster.*CastingFunction)(ptr); //Why does unique_ptr not have operator->* ..?
-		}
+	DLL_LINKAGE CTypeList();
 
-		return ptr;
+	template <typename T>
+	const std::type_info & getTypeInfo(const T * t = nullptr) const
+	{
+		if(t)
+			return typeid(*t);
+		else
+			return typeid(T);
 	}
-	CTypeList & operator=(CTypeList &) = delete;
-
-	TypeInfoPtr getTypeDescriptor(const std::type_info *type, bool throws = true) const; //if not throws, failure returns nullptr
-	TypeInfoPtr registerType(const std::type_info *type);
 
 public:
-
-	CTypeList();
-
-	template <typename Base, typename Derived>
-	void registerType(const Base * b = nullptr, const Derived * d = nullptr)
+	static CTypeList & getInstance()
 	{
-		TUniqueLock lock(mx);
-		static_assert(std::is_base_of<Base, Derived>::value, "First registerType template parameter needs to ba a base class of the second one.");
-		static_assert(std::has_virtual_destructor<Base>::value, "Base class needs to have a virtual destructor.");
-		static_assert(!std::is_same<Base, Derived>::value, "Parameters of registerTypes should be two different types.");
-		auto bt = getTypeInfo(b);
-		auto dt = getTypeInfo(d); //obtain std::type_info
-		auto bti = registerType(bt);
-		auto dti = registerType(dt); //obtain our TypeDescriptor
-
-		// register the relation between classes
-		bti->children.push_back(dti);
-		dti->parents.push_back(bti);
-		casters[std::make_pair(bti, dti)] = std::make_unique<const PointerCaster<Base, Derived>>();
-		casters[std::make_pair(dti, bti)] = std::make_unique<const PointerCaster<Derived, Base>>();
+		static CTypeList registry;
+		return registry;
 	}
 
-	ui16 getTypeID(const std::type_info *type, bool throws = false) const;
-
-	template <typename T>
-	ui16 getTypeID(const T * t = nullptr, bool throws = false) const
+	template<typename T, typename U>
+	void registerType()
 	{
-		return getTypeID(getTypeInfo(t), throws);
+		registerType<T>();
+		registerType<U>();
 	}
 
-	TypeInfoPtr getTypeDescriptor(ui16 typeID) const;
-
-	template<typename TInput>
-	void * castToMostDerived(const TInput * inputPtr) const
+	template<typename T>
+	void registerType()
 	{
-		const auto & baseType = typeid(typename std::remove_cv<TInput>::type);
-		auto derivedType = getTypeInfo(inputPtr);
+		const std::type_info & typeInfo = typeid(T);
 
-		if (strcmp(baseType.name(), derivedType->name()) == 0)
-		{
-			return const_cast<void*>(reinterpret_cast<const void*>(inputPtr));
-		}
+		if (typeInfos.count(typeInfo.name()) != 0)
+			return;
 
-		return std::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>(
-			const_cast<void*>(reinterpret_cast<const void*>(inputPtr)), &baseType,
-			derivedType));
+		typeInfos[typeInfo.name()] = typeInfos.size() + 1;
 	}
 
-	template<typename TInput>
-	std::any castSharedToMostDerived(const std::shared_ptr<TInput> inputPtr) const
+	template<typename T>
+	uint16_t getTypeID(T * typePtr)
 	{
-		const auto & baseType = typeid(typename std::remove_cv<TInput>::type);
-		auto derivedType = getTypeInfo(inputPtr.get());
-
-		if (!strcmp(baseType.name(), derivedType->name()))
-			return inputPtr;
+		static_assert(!std::is_pointer_v<T>, "CTypeList does not supports pointers!");
+		static_assert(!std::is_reference_v<T>, "CTypeList does not supports references!");
 
-		return castHelper<&IPointerCaster::castSharedPtr>(inputPtr, &baseType, derivedType);
-	}
+		const std::type_info & typeInfo = getTypeInfo(typePtr);
 
-	void * castRaw(void *inputPtr, const std::type_info *from, const std::type_info *to) const
-	{
-		return std::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>(inputPtr, from, to));
-	}
-	std::any castShared(std::any inputPtr, const std::type_info *from, const std::type_info *to) const
-	{
-		return castHelper<&IPointerCaster::castSharedPtr>(inputPtr, from, to);
-	}
+		if (typeInfos.count(typeInfo.name()) == 0)
+			return 0;
 
-	template <typename T> const std::type_info * getTypeInfo(const T * t = nullptr) const
-	{
-		if(t)
-			return &typeid(*t);
-		else
-			return &typeid(T);
+		return typeInfos.at(typeInfo.name());
 	}
 };
 
-extern DLL_LINKAGE CTypeList typeList;
-
 /// Wrapper over CTypeList. Allows execution of templated class T for any type
 /// that was resgistered for this applier
 template<typename T>
 class CApplier : boost::noncopyable
 {
-	std::map<ui16, std::unique_ptr<T>> apps;
+	std::map<int32_t, std::unique_ptr<T>> apps;
 
 	template<typename RegisteredType>
 	void addApplier(ui16 ID)
@@ -224,9 +97,8 @@ public:
 	template<typename Base, typename Derived>
 	void registerType(const Base * b = nullptr, const Derived * d = nullptr)
 	{
-		typeList.registerType(b, d);
-		addApplier<Base>(typeList.getTypeID(b));
-		addApplier<Derived>(typeList.getTypeID(d));
+		addApplier<Base>(CTypeList::getInstance().getTypeID<Base>(nullptr));
+		addApplier<Derived>(CTypeList::getInstance().getTypeID<Derived>(nullptr));
 	}
 };
 

+ 0 - 40
lib/serializer/Cast.h

@@ -9,58 +9,18 @@
  */
 #pragma once
 
-#include <typeinfo>
-#include <string>
-#include "CTypeList.h"
-
 VCMI_LIB_NAMESPACE_BEGIN
 
 template<class T, class F>
 inline const T * dynamic_ptr_cast(const F * ptr)
 {
-#ifndef VCMI_APPLE
 	return dynamic_cast<const T *>(ptr);
-#else
-	if(!strcmp(typeid(*ptr).name(), typeid(T).name()))
-	{
-		return static_cast<const T *>(ptr);
-	}
-	try
-	{
-		auto * sourceTypeInfo = typeList.getTypeInfo(ptr);
-		auto * targetTypeInfo = &typeid(typename std::remove_const<typename std::remove_pointer<T>::type>::type);
-		typeList.castRaw((void *)ptr, sourceTypeInfo, targetTypeInfo);
-	}
-	catch(...)
-	{
-		return nullptr;
-	}
-	return static_cast<const T *>(ptr);
-#endif
 }
 
 template<class T, class F>
 inline T * dynamic_ptr_cast(F * ptr)
 {
-#ifndef VCMI_APPLE
 	return dynamic_cast<T *>(ptr);
-#else
-	if(!strcmp(typeid(*ptr).name(), typeid(T).name()))
-	{
-		return static_cast<T *>(ptr);
-	}
-	try
-	{
-		auto * sourceTypeInfo = typeList.getTypeInfo(ptr);
-		auto * targetTypeInfo = &typeid(typename std::remove_const<typename std::remove_pointer<T>::type>::type);
-		typeList.castRaw((void *)ptr, sourceTypeInfo, targetTypeInfo);
-	}
-	catch(...)
-	{
-		return nullptr;
-	}
-	return static_cast<T *>(ptr);
-#endif
 }
 
 VCMI_LIB_NAMESPACE_END

+ 2 - 2
server/CGameHandler.cpp

@@ -463,12 +463,12 @@ void CGameHandler::handleReceivedPack(CPackForServer * pack)
 		PackageApplied applied;
 		applied.player = pack->player;
 		applied.result = succesfullyApplied;
-		applied.packType = typeList.getTypeID(pack);
+		applied.packType = CTypeList::getInstance().getTypeID(pack);
 		applied.requestID = pack->requestID;
 		pack->c->sendPack(&applied);
 	};
 
-	CBaseForGHApply * apply = applier->getApplier(typeList.getTypeID(pack)); //and appropriate applier object
+	CBaseForGHApply * apply = applier->getApplier(CTypeList::getInstance().getTypeID(pack)); //and appropriate applier object
 	if(isBlockedByQueries(pack, pack->player))
 	{
 		sendPackageResponse(false);

+ 2 - 2
server/CVCMIServer.cpp

@@ -485,7 +485,7 @@ void CVCMIServer::threadHandleClient(std::shared_ptr<CConnection> c)
 
 void CVCMIServer::handleReceivedPack(std::unique_ptr<CPackForLobby> pack)
 {
-	CBaseForServerApply * apply = applier->getApplier(typeList.getTypeID(pack.get()));
+	CBaseForServerApply * apply = applier->getApplier(CTypeList::getInstance().getTypeID(pack.get()));
 	if(apply->applyOnServerBefore(this, pack.get()))
 		addToAnnounceQueue(std::move(pack));
 }
@@ -502,7 +502,7 @@ void CVCMIServer::announcePack(std::unique_ptr<CPackForLobby> pack)
 		c->sendPack(pack.get());
 	}
 
-	applier->getApplier(typeList.getTypeID(pack.get()))->applyOnServerAfter(this, pack.get());
+	applier->getApplier(CTypeList::getInstance().getTypeID(pack.get()))->applyOnServerAfter(this, pack.get());
 }
 
 void CVCMIServer::announceMessage(const std::string & txt)