Skip to content

Instantly share code, notes, and snippets.

@DrkWithT
Created June 6, 2024 17:38
Show Gist options
  • Save DrkWithT/31872911be463445b8dbc72fa86b50ca to your computer and use it in GitHub Desktop.
Save DrkWithT/31872911be463445b8dbc72fa86b50ca to your computer and use it in GitHub Desktop.
#include <iostream>
/*
Attempt at CRTP visitor sample
DrkWithT
*/
/// Forward decls. of visitable objects
class OneBox;
class TwoBox;
/// Prints any XXBox's info
struct BoxVisitor
{
BoxVisitor() = default;
void visitOneBox(const OneBox& one) const;
void visitTwoBox(const TwoBox& two) const;
};
/// CRTP compile-time interface for an XXBox
template <typename Derived>
class Base
{
private:
[[nodiscard]] Derived* getDerivedPtr() { return static_cast<Derived*>(this); }
public:
Base() = default;
void acceptVisitor(const BoxVisitor& printer)
{
/// Here, I start double dispatch with the appropriate derived class's. The object is prompted to accept the printer.
getDerivedPtr()->acceptVisitor(printer);
}
};
class OneBox : public Base<OneBox>
{
private:
int a;
public:
constexpr OneBox(int a_)
: a {a_} {}
[[nodiscard]] int getA() const { return a; }
void acceptVisitor(const BoxVisitor& printer)
{
// Here, the double dispatch is about to finish: the OneBox class knows by itself how to handle this visitation.
printer.visitOneBox(*this);
}
};
class TwoBox : public Base<TwoBox>
{
private:
int a;
int b;
public:
constexpr TwoBox(int a_, int b_)
: a {a_}, b {b_} {}
[[nodiscard]] int getA() const { return a; }
[[nodiscard]] int getB() const { return b; }
void acceptVisitor(const BoxVisitor& printer)
{
printer.visitTwoBox(*this);
}
};
/// Post-forward definitions of visitor's methods to help linker resolve dummy calls from forward decls.
void BoxVisitor::visitOneBox(const OneBox& one) const
{
std::cout << "OneBox {" << one.getA() << '}' << '\n';
}
void BoxVisitor::visitTwoBox(const TwoBox& two) const
{
std::cout << "TwoBox {" << two.getA() << ',' << two.getB() << '}' << '\n';
}
int main()
{
// create visitable objects
OneBox single {42};
TwoBox couple {20, 24};
// create printing visitor
BoxVisitor box_display;
// test visit methods
box_display.visitOneBox(single);
box_display.visitTwoBox(couple);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment