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;
}
The approach that you are taking is similar to how the boost serialization library is implemented, with the difference that in their case they are overloading
operator&(binary and, not address-of) to interact with the library. Then the visitors will use a singleserializeoperation on the type.Now, the problem is that I don’t really understand the question:
Do you mean providing a single
operator<<that will take any visitor(serializer) type? If that is the question, and without going into much detail, you could try using inheritance and the CRTP to solve this. Implement the operator as a member function in a templated base of all your visitors that takes the concrete visitor as argument.I am not too sure how that would apply to the comparison operators, while
operator<<andoperator>>look natural for serialization, they would be surprising for any other operation.