I need to write a program implementing the visitor design pattern. The problem is that the base visitor class is a template class. This means that BaseVisited::accept() takes a template class as a parameter and since it uses 'this' and i need 'this' to point to the correct runtime instance of the object, it also needs to be virtual.
I'd like to know if there's any way around this problem.
template <typename T>
class BaseVisitor {
public:
BaseVisitor();
T visit(BaseVisited *visited);
virtual ~BaseVisitor();
}
class BaseVisited {
BaseVisited();
template <typename T>
virtual void accept(BaseVisitor<T> *visitor) { visitor->visit(this); }; // problem
virtual ~BaseVisited();
}
No, template member functions cannot be virtual.
A non-template class can have template member functions, if required. Notice the syntax. Unlike a member function for a template class, a template member function is just like a free template function but scoped to its containing class.
A virtual function cannot be global or static because, by definition, a virtual function is a member function of a base class and relies on a specific object to determine which implementation of the function is called. You can declare a virtual function to be a friend of another class.
A C++ virtual function is a member function in the base class that you redefine in a derived class. It is declared using the virtual keyword. It is used to tell the compiler to perform dynamic linkage or late binding on the function.
What you should do is separate the BaseVisitor.
class BaseVisited;
class BaseVisitorInternal {
public:
virtual void visit(BaseVisited*) = 0;
virtual ~BaseVisitorInternal() {}
};
class BaseVisited {
BaseVisited();
virtual void accept(BaseVisitorInternal* visitor) { visitor->visit(this); }
};
template<typename T> class BaseVisitor : public BaseVisitorInternal {
void visit(BaseVisited* visited);
};
If you need BaseVisited's derived classes to be templated too AND pass their correct types/overloads to visit, you're officially dead.
I came up with something slightly different than DeadMG:
class BaseVisited;
class IVisitor {
public:
virtual void visit(BaseVisited *visited) = 0;
virtual ~IVisitor();
};
template <typename T>
class BaseVisitor : public IVisitor {
public:
BaseVisitor();
virtual void visit(BaseVisited *visited);
virtual ~BaseVisitor();
virtual T result();
};
class BaseVisited {
public:
BaseVisited();
virtual void accept(IVisitor *visitor) { visitor->visit(this); };
virtual ~BaseVisited();
};
Mine has an extra result()
member function that lets you retrieve the result of the last visit.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With