#include <iostream>

class DerivedStuff1 {
  public:
   static void eval() { std::cout << "Evaluating DerivedStuff1\n"; }
};

class DerivedStuff2 {
  public:
   static void eval() { std::cout << "Evaluating DerivedStuff2\n"; }
};


class DerivedClass1; class DerivedClass2;
class BaseClassVisitor {
  public:
    virtual void visit(DerivedClass1&) = 0;
    virtual void visit(DerivedClass2&) = 0;
};

class BaseClass {
  public:
    virtual void accept(BaseClassVisitor& v) = 0;
};

class DerivedClass1 : public BaseClass
{
  public:
    virtual void accept(BaseClassVisitor& v) { v.visit(*this); }
};

class DerivedClass2 : public BaseClass
{
  public:
    virtual void accept(BaseClassVisitor& v) { v.visit(*this); }
};


template <typename StuffType>
class EvalVisitor : public BaseClassVisitor
{
    virtual void visit(DerivedClass1&) {
        std::cout << "We are in DerivedClass1: ";
        StuffType::eval();
    }
    virtual void visit(DerivedClass2&) {
        std::cout << "We are in DerivedClass2: ";
        StuffType::eval();
    }

};

int main()
{
    EvalVisitor<DerivedStuff1> e1;
    EvalVisitor<DerivedStuff2> e2;

    BaseClass* c1 = new DerivedClass1;

    c1->accept(e1);
    c1->accept(e2);

    BaseClass* c2 = new DerivedClass2;

    c2->accept(e1);
    c2->accept(e2);

    return 0;
}
