#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <memory>

struct Animal
{ virtual void say() const {std::cout << "...\n";} };

struct Dog : Animal
{ virtual void say() const override {std::cout << "Woof\n";} };

struct Cat : Animal
{ virtual void say() const override {std::cout << "Meow\n";} };

struct Cow : Animal
{ virtual void say() const override {std::cout << "Moo\n";} };

using Animals = std::vector<std::unique_ptr<Animal>>;

Animals populate(std::istream& in)
{
    Animals result;
    std::string animal;
    while(in >> animal)
        if (animal == "cow")
            result.emplace_back(new Cow);
        else if (animal == "cat")
            result.emplace_back(new Cat);
        else if (animal == "dog")
            result.emplace_back(new Dog);
        else
            result.emplace_back(new Animal);
    return result;
}

int main()
{
    std::istringstream input("cat cat cow dog cow foo");
    auto animals = populate(input);
    for(const auto& v: animals)
        v -> say();
}
