#include <memory>
#include <string>
#include <unordered_map>
#include <iostream>
#include <cstdlib>

using namespace std;


struct Animal {
	virtual void say(ostream &ostr) const = 0;
};

struct Dog: public Animal {
	virtual void say(ostream &ostr) const {
		ostr << "Bark!";
	}
};

struct Cat: public Animal {
	virtual void say(ostream &ostr) const {
		ostr << "Meow!";
	}
};

typedef unordered_map<string, unique_ptr<Animal>> AnimalMap;

static const char *ANIMAL_ENV = "ANIMAL";
static const char *ANIMAL_DEFAULT = "Dog";

int main(int, char const *[])
{
	static const AnimalMap animal_map = []() {
		AnimalMap res;
		res.emplace("Dog", make_unique<Dog>());
		res.emplace("Cat", make_unique<Cat>());
		return res;
	}();

	const char *animal = getenv(ANIMAL_ENV);
	if (animal == nullptr) {
		animal = ANIMAL_DEFAULT;
	}

	auto hit = animal_map.find(animal);
	if (hit != animal_map.cend()) {
		hit->second->say(cout);
		cout << endl;
	} else {
		cerr << "Error: Animal not found: " << animal << endl;
	}

	return 0;
}
