#include <iostream>
#include <memory>
#include <map>

template <class X>
X& Singleton()
{
    static X x;
	return x;
}

template<class GUID_T, class MAP_T, class T>
class TypeFactory {
protected:
	bool ContainsInternal(MAP_T id) {
		auto it = types.find(id);
		return (it != types.end());
	}

	typedef GUID_T GUID;
	inline virtual MAP_T GetTypeID(GUID guid) = 0;
	std::map<MAP_T, T> types;
public :
	void Add(GUID guid, const T & value) {
		auto id = GetTypeID(guid);
		if(!ContainsInternal(id)) {
			types.insert(std::make_pair(id, T(value)));
		}
	}

	bool Contains(GUID guid) {
		return ContainsInternal(GetTypeID(guid));
	}

	std::shared_ptr<T> Get(GUID guid) {
		auto id = GetTypeID(guid);
		std::shared_ptr<T> result;
		auto it = types.find(id);
		if(it != types.end()) {
			result = std::make_shared<T>(it->second);
		}
		return result;
	}

	std::map<MAP_T, T> & GetAll() {
		return types;
	}
};

template<class T>
class IntTypeFactory : public TypeFactory<int, int, T> {
protected:
	inline virtual int GetTypeID(GUID guid) {
		return guid;
	}
};
class Type {
public: int a;
};

int main() {
	IntTypeFactory<Type> & Types (Singleton< IntTypeFactory<Type> >());
	IntTypeFactory<Type> & Types2 (Singleton< IntTypeFactory<Type> >());

	auto t_in = Type();
	t_in.a = 10;
	Types.Add(1, t_in);
	auto t_out = Types2.Get(1);
	std::cout << t_out->a << std::endl;
	return 0;
}