次のような訪問関数を備えたクラスがいくつかあります。
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);
}
};
私には次のような訪問者がいます:
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;
};
訪問者ごとに、ストリーム演算子を定義します。
std::ostream& operator<<(std::ostream& stream, const Person& p)
{
PrintVisitor printer(stream);
p.visit(printer);
return stream;
}
訪問可能なクラスを受け入れる単一の演算子<<を提供することは可能ですか?
(現在、私は印刷を実験しているだけですが、実際にはjsonのシリアル化、逆シリアル化、そしておそらく等式および小なり演算子を実装したいと思っています。
アップデート
私はDavidsソリューションを使用しました:
CRTPの基本クラス:
template <class T>
struct Visitable {};
訪問可能なすべてのクラスはそこから継承します。
struct Person : Visitable<Person> { ... }
演算子と関数はそのようにテンプレート化されており、静的キャストを使用してクラスにアクセスします。
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;
}