The fact that the method accepts a "key", which seems to be really a type (the type of the returned component), tells me that the type is still unknown before execution. If this is the case, then a compile-time mechanism such as templates will not execute.
The only option is to return a pointer to the base class. And usually, when this template is used, only virtual methods are called to the base class, so the actual type of the derived class does not matter (so static_cast or dynamic_cast is not required).
Edit:
As PhilCK noted in the comments, this type is actually known at compile time. If so, then a dynamic type search was never required, and simple factory methods could be used:
class GameObject { A getComponentA(); B getComponentB(); C getComponentC(); // etc. } // which is more or less identical to: class ComponentFactory { public: virtual Component* create() = 0; }; class GameObject { std::map<std::string,ComponentFactory> m; public: GameObject() { // presumably a private map has to be populated with string -> factory methods here } template<class T> T* getComponent(const std::string& s) { // either the static_cast is needed here, or an alternate (messier) // implementation of getComponent is needed. // it still possible for the wrong type to be passed (by mistake) // and the compiler won't catch it (with static_cast). Since this could lead // to heap corruption the only safe way with this type of // implementation is dynamic_cast. return static_cast<T>(m[s].create()); } }; // this doesn't even compile: // return types: class GameObject { template <class T> T* getComponent(const std::string& s) { if (s == "A") return new A(); else if (s == "B") return new B(); // etc.. else throw runtime_error("bad type"); } }
So, there are two options, as I see it.
1) use simple factory methods in which templates are not needed at all. 2) use the implementation of the map β factory along with dynamic_cast (which seems to be aimed at using the creation of a dynamic type) and is actually unnecessarily complicated if dynamic types are not needed
source share