#include <iostream>
#include <memory>

class any_ptr
{
    struct WrapperBase
    {
    	virtual ~WrapperBase(){}
    };

    template<typename T>
    struct Wrapper : WrapperBase, T
    {
		template<typename ... Args>
    	Wrapper( Args&&... args ):
    		T( std::forward<Args>(args)... ) {}
    };

    std::unique_ptr<WrapperBase> mPtr;

	any_ptr( std::unique_ptr<WrapperBase> ptr ):
		mPtr{ std::move(ptr) } {}

public:

	template< typename T >
	explicit operator T*()
	{
		return dynamic_cast<T*>(mPtr.get());
	}

	template< typename T >
	explicit operator T const*() const
	{
		return dynamic_cast<T*>(mPtr.get());
	}

	template<typename T>
	friend any_ptr make_any_ptr( T&& t )
	{
		return std::unique_ptr<WrapperBase>{ new Wrapper<T>{ std::forward<T>(t) } };
	}

	template< typename T,
	          typename ... Args >
	friend any_ptr make_any_ptr( Args&&... args )
	{
		return std::unique_ptr<WrapperBase>{ new Wrapper<T>{ std::forward<Args>(args)... } };
	}
};

////////////////////////////////////////////////////////////////////////////////

template <class T>
bool inspect(any_ptr& p, void (&fun)(T))
{
	using actual_t = typename std::remove_reference<T>::type;

	if( actual_t* t = static_cast<actual_t*>(p) )
		fun(*t);

	return false;
}

////////////////////////////////////////////////////////////////////////////////

class printable
{
public:
	virtual void print() const = 0;
};

////////////////////////////////////////////////////////////////////////////////

#include <string>
using namespace std;

class foo : public printable
{
public:
	foo(string const& s) : m_s(s) {}

	virtual void print() const
	{
		cout << "foo: " << m_s << "\n";
	}

private:
	string m_s;
};

class bar : public printable
{
public:
	bar(int i) : m_i(i) {}

	virtual void print() const
	{
		cout << "bar: " << m_i << "\n";
	}

private:
	int m_i;
};

////////////////////////////////////////////////////////////////////////////////

void print_printable(printable& p)
{
	p.print();
}

////////////////////////////////////////////////////////////////////////////////

int main()
{
	auto f = make_any_ptr(foo("foo"));
	auto b = make_any_ptr(bar(42));

	inspect(f, print_printable);
	inspect(b, print_printable);
}