I've got a few classes with the with a visit function like so:
struct Person { std::string name; unsigned age; template<class Visitor> void visit(Visitor& c) { c("name", name); c("age", age); } template<class Visitor> void visit(Visitor& c) const { c("name", name); c("age", age); } }; I have a visitor like:
struct PrintVisitor { PrintVisitor(std::ostream& stream) : m_stream(stream) {} template<class T> void operator()(const std::string& name, const T& v) { m_stream << name << ": " << v << std::endl; } private: std::ostream& m_stream; }; For each visitor I want to define a stream operator:
std::ostream& operator<<(std::ostream& stream, const Person& p) { PrintVisitor printer(stream); p.visit(printer); return stream; } Is it possible to provide a single operator<< that accepts any Visitable class?
(Right now, I'm just experimenting with printing, but I actually want to implement json serialization, deserialization and perhaps equality and less-than operators.
UPDATE
I used Davids solution:
Base class for CRTP:
template <class T> struct Visitable {}; All visitable classes inherit from there:
struct Person : Visitable<Person> { ... } Operators and functions are templated as so, and use a static cast to visit the class:
template<class T> std::ostream& operator<<(std::ostream& stream, const Visitable<T>& p) { PrintVisitor printer(stream); static_cast<const T&>(p).visit(printer); return stream; }