C++11中auto声明变量报错:AnimalRenderer<auto>无效使用问题
Hey there! Let's walk through what's causing that error and how to fix it, especially since you're coming from Java and working within C++11 constraints.
First, Why the Error Happens
That line AnimalRenderer<auto> renderer; is invalid for two critical reasons in C++11:
autocan't be used as a template parameter here. In C11,autoonly deduces variable types from their initializers—you can't stick it inside angle brackets to create a generic template instance. (Even C17's limited support forautoas a template parameter wouldn't solve your core problem.)DogRendererandCatRendererare distinct, unrelated types. Unlike Java's generics (which use type erasure), C++ templates generate unique types for each template argument. Your original code gives these renderers no shared base class, so you can't assign them to the same variable.
On top of that, you've got an object slicing issue: std::vector<Animal> stores copies of Animal objects, not your Dog/Cat subclasses. When you put a Dog into this vector, it gets stripped down to just an Animal, losing all subclass-specific data—so your renderer would never get a real Dog to work with.
Step-by-Step Fix
1. Fix Object Slicing with Smart Pointers
Instead of storing Animal objects directly, use std::unique_ptr<Animal> (C++11's safe, lightweight smart pointer) to hold references to your subclass objects. This avoids slicing and manages memory automatically:
// Replace your map type with this std::map<AnimalType, std::vector<std::unique_ptr<Animal>>> animalMap;
2. Create a Polymorphic Base Renderer
To handle different renderer types uniformly, make a non-template base class that all your renderers inherit from. This lets you use polymorphism to call the right draw method:
#include <memory> // Required for std::unique_ptr in C++11 // Base class for all renderers (non-template) class BaseRenderer { public: virtual ~BaseRenderer() = default; // Required for safe polymorphic deletion virtual void draw(Animal* animal) = 0; // Virtual method to override }; // Update your template renderer to inherit from BaseRenderer template<class T> class AnimalRenderer : public BaseRenderer { public: // Implement the base class method, cast to the specific type void draw(Animal* animal) override { // C++11's override keyword catches typos in method names/signatures if (T* typedAnimal = dynamic_cast<T*>(animal)) { drawImpl(typedAnimal); // Delegate to subclass-specific logic } } private: // Subclasses will implement this with their actual rendering code virtual void drawImpl(T* entity) = 0; }; // Update DogRenderer and CatRenderer to use the new structure class DogRenderer : public AnimalRenderer<Dog> { private: void drawImpl(Dog* entity) override { // Add your Dog-specific rendering logic here } }; class CatRenderer : public AnimalRenderer<Cat> { private: void drawImpl(Cat* entity) override { // Add your Cat-specific rendering logic here } };
3. Rewrite the GeneralRenderer's draw Method
Now you can use a smart pointer to hold the base renderer, assign the correct subclass, and call the polymorphic draw method safely:
class GeneralRenderer { public: void draw(std::map<AnimalType, std::vector<std::unique_ptr<Animal>>> animalMap) { // Use auto& to avoid copying large map entries for (auto& entry : animalMap) { std::unique_ptr<BaseRenderer> renderer; switch (entry.first) { case AnimalType::Dog: renderer.reset(new DogRenderer()); break; case AnimalType::Cat: renderer.reset(new CatRenderer()); break; default: // Handle unknown animal types (e.g., skip or throw an error) continue; } // Iterate over the smart pointers to animals for (auto& animal : entry.second) { renderer->draw(animal.get()); // Get the raw pointer from unique_ptr } } } };
Key C++11 Notes
std::unique_ptr: This is C++11's preferred way to manage dynamic memory—no manualdeleteneeded, and it prevents memory leaks.override: Optional but highly recommended—this keyword ensures you're actually overriding a virtual method from the base class, catching bugs early.- Dynamic Cast: We use
dynamic_cast<T*>to safely convert theAnimal*to the subclass type—this returnsnullptrif the cast fails, avoiding undefined behavior.
内容的提问来源于stack exchange,提问作者Ochalhi

