Ochalhi
Ochalhi

Reputation: 31

Invalid use of auto when declaring a variable C++, C++11

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

Answers (3)

Bathsheba
Bathsheba

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

Gem Taylor
Gem Taylor

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

Michael Aigner
Michael Aigner

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

Related Questions