#include <vector>
#include <iostream>
#include <string>

class Elf
{
public:

    Elf(std::string const& name)
        : name { name }
    { }
    
    virtual ~Elf() = default;

    virtual std::string handle(std::string const& gift) const = 0;

    std::string get_name() const
    {
        return name;
    }

private:

    std::string name;
    
};

class Wrapper : public Elf
{
public:

    Wrapper(std::string const& name, std::string const& color)
        : Elf { name }, color { color }
    { }
    
    std::string handle(std::string const& gift) const override
    {
        return gift + " wrapped in " + color + " paper";
    }
    
private:

    std::string color;
    
};

class Boxer : public Elf
{
public:

    using Elf::Elf;
    
    std::string handle(std::string const& gift) const override
    {
        return "box containing a " + gift;
    }
};

int main()
{
    std::vector<Elf*> elves {
        new Wrapper{"Eminelf", "blue"},
        new Boxer{"Elf Mayweather"},
        new Boxer{"Mike Elfson"},
        new Wrapper{"Elfpac", "red"}
    };

    std::string gift { "Book" };
    for (Elf* elf : elves)
    {
        gift = elf->handle(gift);
    }
    std::cout << gift << std::endl << std::endl;

    std::cout << "This gift was packaged by: " << std::endl;
    for (Elf* elf : elves)
    {
        std::cout << elf->get_name() << std::endl;
    }
}