#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

//========================================================================
//Reference-wrapping utility functions:

/*template<class ContainerType, class ElementType = typename ContainerType::value_type >
std::vector<std::reference_wrapper<ElementType>> RefWrapAsVector(ContainerType &container)
{
	//Create a vector of std::reference_wrappers wrapping 'ElementType'
	return std::vector<std::reference_wrapper<ElementType>>(std::begin(container), std::end(container));
}*/

//And the const version:
template<class BaseType, class ContainerType>
std::vector<std::reference_wrapper<const BaseType>> RefWrapAsVector(const ContainerType &container)
{
	//Create a vector of std::reference_wrappers wrapping 'BaseType'.
	return std::vector<std::reference_wrapper<const BaseType>>(std::begin(container), std::end(container));
}


//========================================================================
//Your classes:

class Animal
{
	public:
    virtual void Talk() const { std::cout << "<generic animal noise>" << std::endl; }
};

class Cat : public Animal
{
	public:
	Cat(std::string text) : kittySpeach(text) { }
	
	void Talk() const override  { std::cout << kittySpeach << std::endl; }
	
	private:
	std::string kittySpeach;
};


void ForceAnimalsToTalk(const std::vector<std::reference_wrapper<const Animal>> &animals)
{
	for(const Animal &animal : animals)
	{
		animal.Talk();
	}
}

//========================================================================

int main()
{
	//Really just an excuse to add moar cats to teh code.
	std::vector<Cat> myCats = {Cat("Meow"), Cat("Purr"), Cat("Meowmeow"), Cat("*yawns adorably*")};
	
	ForceAnimalsToTalk(RefWrapAsVector<Animal>(myCats));
	
	return 0;
}