namespace loco
{
-struct ThrowNotImplemented
-{
- /**
- * GCC rejects the following implementation of "CanonicalNodeVisitorImpl::visit":
- *
- * virtual T visit(const CLASS *)
- * {
- * Fallback f;
- * return f.call<T>();
- * }
- *
- * Let us pass "nullptr" of T * type (which serves as a type tag) as a workaround.
- *
- * TODO Remove this workaround if possible
- */
- template <typename T> T call(const T *) const
- {
- // Throw NYI exception
- throw std::runtime_error{"Not implemented, yet"};
- }
-};
-
/**
- * DO NOT use this class. Use CanonicalNodeVisitor or CanonicalNodeVisitorImpl instead.
+ * DO NOT use this class. Use CanonicalNodeVisitor instead.
*/
template <typename T> struct CanonicalNodeVisitorBase
{
#undef CANONICAL_NODE
};
-template <typename T, typename Fallback>
-struct CanonicalNodeVisitorImpl : public CanonicalNodeVisitorBase<T>
+template <typename T> struct CanonicalNodeVisitor : public CanonicalNodeVisitorBase<T>
{
- virtual ~CanonicalNodeVisitorImpl() = default;
+ virtual ~CanonicalNodeVisitor() = default;
-#define CANONICAL_NODE(OPCODE, CLASS) \
- virtual T visit(const CLASS *) \
- { \
- Fallback f; \
- return f.call(static_cast<const T *>(nullptr)); \
- }
+#define CANONICAL_NODE(OPCODE, CLASS) \
+ virtual T visit(const CLASS *node) { return visit(static_cast<const Node *>(node)); }
#include "CanonicalNodes.lst"
#undef CANONICAL_NODE
-};
-template <typename T>
-struct CanonicalNodeVisitor : public CanonicalNodeVisitorImpl<T, ThrowNotImplemented>
-{
- virtual ~CanonicalNodeVisitor() = default;
+ /// @brief Default fallback
+ virtual T visit(const Node *) { throw std::runtime_error{"Not implemented, yet"}; }
};
} // namespace loco
TEST(CanonicalNodeTest, visitor_with_user_default_impl)
{
- struct MyFallback
- {
- uint32_t call(const uint32_t *) const { return 256; }
- };
-
- struct MyVisitor final : public loco::CanonicalNodeVisitorImpl<uint32_t, MyFallback>
+ struct MyVisitor final : public loco::CanonicalNodeVisitor<uint32_t>
{
+ // This visitor returns 128 if it visits a Forward node.
uint32_t visit(const loco::Forward *) final { return 128; }
+
+ // Otherwise, this visitor returns 256.
+ uint32_t visit(const loco::Node *) final { return 256; }
};
loco::Forward forward;