vendredi 9 juillet 2021

Implement Visitor Pattern with Templated Visitor Class

In my visitor pattern implementation I am trying to use a templated return type for Visitor implementation. I currently have the following implementation.

test.h

#include <string>

template <class T> class ExprVisitor;

template <class T> class Expr {
 public:
   virtual T Accept(ExprVisitor<T>* visitor){};
};

template <class T> class Literal : public Expr<T> {
 public:
  Literal(std::string value) : value_(value) {}
  T Accept(ExprVisitor<T>* visitor) { return visitor->VisitLiteralExpr(this); }

  std::string value_;
};

template <class T> class ExprVisitor {
 public:
  T VisitLiteralExpr(Expr<T>* expr);
};

test.cc

#include <iostream>
#include <string>

#include "test.h"

using std::string;

class AstPrinter : public ExprVisitor<string> {
 public:
  string PrintAST(Expr<string>* expr) { return expr->Accept(this); }

  string VisitLiteralExpr(Expr<string>* e) {
    Literal<string>* expr = reinterpret_cast<Literal<string>*>(e);
    return expr->value_;
  }
};

int main(int argc, char** argv) {
  Expr<string>* expression = new Literal<string>("45.67");
  std::cout << (new AstPrinter())->PrintAST(expression);
  return 0;
}

However, the linker complains that it is unable to find the definition for ExprVisitor.

$ g++ -o test test.cc test.h
/tmp/cc2y8pdx.o: In function `Literal<std::__cxx11::basic_string<char,    std::char_traits<char>, std::allocator<char> > >::Accept(ExprVisitor<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >*)':
test.cc:(.text._ZN7LiteralINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE6AcceptEP11ExprVisitorIS5_E[_ZN7LiteralINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE6AcceptEP11ExprVisitorIS5_E]+0x27): undefined reference to `ExprVisitor<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::VisitLiteralExpr(Expr<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >*)'
collect2: error: ld returned 1 exit status

Can I get some help in understanding what the issue is here?

Aucun commentaire:

Enregistrer un commentaire