Reputation: 31
Whenever I try to compile my code I get an invalid use of auto. Coming from a Java background, I am not sure if I quite understand C++ templates. It seems like the compiler can infer the type. I am limited to C++11.
The error occurs in the GeneralRenderer.
Animal classes
class Animal {};
class Dog : public Animal {};
class Cat : public Animal {};
enum AnimalType {
Dog,
Cat
};
Render Classes
template<class T>
class AnimalRenderer {
virtual void draw(T entity) = 0;
};
class DogRenderer : public AnimalRenderer<Dog> {};
class CatRenderer : public AnimalRenderer<Cat> {};
Logic
class GeneralRenderer {
public:
void draw(
std::map<AnimalType, std::vector<Animal>> animalMap) {
for (auto entry: animalMap) {
AnimalRenderer<auto> renderer; // <--- Causes the error
switch (entry.first) {
case Dog:
renderer = DogRenderer();
break;
case Cat:
renderer = CatRenderer();
break;
}
for (auto animal: entry.second) {
renderer.draw(entry);
}
}
};
};
Upvotes: 3
Views: 402
Reputation: 234655
Informally speaking, auto
can be used to declare and initialise a type at the same time. Then the compiler can infer the type from the value used to initialise the variable.
But that's not the case here; a statement like
auto n;
will fail similarly.
Note that auto
merely stands in for a type that is known at compile time. It's there to make code more readable although its use is occasionally obligatory such as when working with lambda functions. It is not a variant-type construct cf. std::variant
say of C++17.
Finally note that a std::map
is a very different beast to a java.util.Map
. There's no type erasure in C++ so a std::map<A, B>
is a fundamentally different type to a std::map<C, D>
if A
is a different type to C
and / or B
differs from D
. Furthermore, C++ allows you to store value types in maps.
Upvotes: 8
Reputation: 5613
To get the result you want you effectively need to move the second for-loop inside the cases, where the deduction can be resolved for each case.
You don't want code duplication, so ideally you want a template function you can call to do the second loop. On the latest c++ standards you might also be able to declare a template lambda function.
That said, architecturally, I would suggest adding an interface base class for AnimalRenderer, and then you can declare a simple pointer to that base class, especially as you have already declared draw as virtual.
Upvotes: 1
Reputation: 5160
As the other users already say, auto can‘t work without a righthand variable.
I think you should remove the template annotation from AnimalRenderer, then you can use the classes normally.
Upvotes: 1