In C++14 you can use the following template to print any object which has a T::print(std::ostream&)const; member.
template<class T>
auto operator<<(std::ostream& os, T const & t) -> decltype(t.print(os), os)
{
t.print(os);
return os;
}
In C++20 Concepts can be used.
template<typename T>
concept Printable = requires(std::ostream& os, T const & t) {
{ t.print(os) };
};
template<Printable T>
std::ostream& operator<<(std::ostream& os, const T& t) {
t.print(os);
return os;
}