#include <iostream>
#include <sstream>
#include <string>

struct printable
{
	template <typename T>
	printable(T const* value)
		: data_(value), to_string_impl_(&printable::to_string_impl<T>)
	{}

	std::string to_string() const
	{
		return to_string_impl_(data_);
	}

private:
	void const* data_;
	std::string (* to_string_impl_) ( void const*);

	template <typename T>
	static std::string to_string_impl(void const* data)
	{
		std::ostringstream oss;
		oss << *static_cast<T const*>(data);
		return oss.str();
	}
};

int main()
{
	int i = 42;
	double d = 3.14;

	printable a(&i), b(&d);

	std::cout << "i: " << a.to_string() << '\n';
	std::cout << "d: " << b.to_string() << '\n';
}