Back in the days of C and no templates... we had void pointers. Good thing they weren't made obsolete, because you have just seen that templates aren't omnipotent gods. This situation is perfect for some void pointer hacks.

Here, I tried to make an example that was as simple as possible:

Edit: The example below makes a dangerous use of `shared_ptr`, please refer to the edit below.

		struct ResourceManager {
			
			typedef std::function<void* ()> TFactoryFunctor;
			
			std::map<std::string, TFactoryFunctor> m_factories;
			
			void subscribe (std::string key, TFactoryFunctor factory) {
				m_factories[key] = factory;
			}
			
			template <class T>
			std::shared_ptr<T> load (std::string key) {
				auto& factoryFunctor = m_factories.at(key);
				void* ptr = factoryFunctor();
				
				return std::shared_ptr<T>(static_cast<T*>(ptr));
			}
			
		};

		struct ResourceFactory {
			
			std::string m_path;
			
			void setFilePath (std::string path) {
				m_path = path;
			}
			
			std::string getFilePath() const {
				return m_path;
			}
			
			virtual void* load() =0;
			
			void* operator() () {
				return this->load();
			}
			
		};

		struct TextureFactory : ResourceFactory {
			
			std::shared_ptr<Texture> m_texPtr;
			Texture* m_tex;
			
			TextureFactory (std::string fileName) {
				setFilePath(TEXTURES_FOLDER + fileName);
			}
			
			void* load() override {
				if (!m_texPtr) {
					m_tex = new Texture();
					m_tex->loadFromFile(getFilePath());
					
					m_texPtr = std::shared_ptr<Texture>(m_tex);
				}
				
				return m_tex;
			}
			
		};

		// ---

		ResourceManager daMan;

		void subscribeTextures() {
			daMan.subscribe("hero", TextureFactory("hero.png"));
			daMan.subscribe("foe", TextureFactory("foe.png"));
			daMan.subscribe("tileset", TextureFactory("tileset.png"));
		}
		
		void loadHeroTexture (Hero& hero) {
			auto texPtr = daMan.load<Texture>("hero");
			
			hero.claimOwnership(texPtr); // Maybe you want to keep track of who's using the resource?
			hero.sprite.setTexture(*texPtr);
		}

I didn't test this code to make sure that it's functional and I'm not sure whether it's a good idea to manipulate a raw pointer that's stored in a `shared_ptr` in the way within `TextureFactory::load`, but I hope you get the idea.

In a different, more object-oriented language you would probably use `object` (or some other more specialized base class) and downcasts instead of `void*`, but C++ doesn't have such luxuries. Maybe you can make your own `ResourceBase` base class? You'd have to make _some_ wrappings, do so at your own expenses.

Edit: I have found that the use of `shared_ptr` in my example is erroneous and can lead to multiple deletions of the resource. Please refer to the following example which, while also untested, doesn't showcase a dangerous practice:

		struct ResourceManager {
			
			typedef std::function<std::shared_ptr<void> ()> TFactoryFunctor;
			
			std::map<std::string, TFactoryFunctor> m_factories;
			
			void subscribe (std::string key, TFactoryFunctor factory) {
				m_factories[key] = factory;
			}
			
			template <class T>
			std::shared_ptr<T> load (std::string key) {
				auto& factoryFunctor = m_factories.at(key);
				
				std::shared_ptr<void> ptr = factoryFunctor();
				
				// Here we use the "aliasing" constructor of shared_ptr, which will allow us to use the same reference counting of
				// the shared_ptr within the factory.
				// 
				// Back in the previous example, this returned shared_ptr would have had a different referece counting from the
				// shared_ptr within the factory and this would have lead to the pointed resource getting destroyed at least twice
				// once all shared_ptr's stopped point to it.
				return std::shared_ptr<T>(ptr, static_cast<T*>(ptr.get()));
			}
			
		};

		struct ResourceFactory {
			
			std::string m_path;
			
			void setFilePath (std::string path) {
				m_path = path;
			}
			
			std::string getFilePath() const {
				return m_path;
			}
			
			virtual void* load() =0;
			
			void* operator() () {
				return this->load();
			}
			
		};

		struct TextureFactory : ResourceFactory {
			
			// Now, only one shared_ptr is enough. We don't need to keep a raw pointer around.
			std::shared_ptr<Texture> m_texPtr;
			
			TextureFactory (std::string fileName) {
				setFilePath(TEXTURES_FOLDER + fileName);
			}
			
			std::shared_ptr<void> load() override {
				if (!m_texPtr) {
					m_texPtr = std::make_shared<Texture>();
					m_texPtr->loadFromFile(getFilePath());
				}
				
				// A shared_ptr<void> is essentially a void*, we're not changing much here.
				return m_texPtr;
			}
			
		};

		// ---

		ResourceManager daMan;

		void subscribeTextures() {
			daMan.subscribe("hero", TextureFactory("hero.png"));
			daMan.subscribe("foe", TextureFactory("foe.png"));
			daMan.subscribe("tileset", TextureFactory("tileset.png"));
		}

		void loadHeroTexture (Hero& hero) {
			auto texPtr = daMan.load<Texture>("hero");
			
			hero.claimOwnership(texPtr); // Maybe you want to keep track of who's using the resource?
			hero.sprite.setTexture(*texPtr);
		}