Способ удалить избыточность шаблона посетителя? - PullRequest
0 голосов
/ 21 октября 2019

Итак, я впервые играю с шаблоном посетителя и удивляюсь, почему я должен написать функцию accept несколько раз для каждого производного класса.

class object
{
public:
    virtual void accept(visitor *v) { v->visit(this); }

// ....
};

class derived : public object
{
public:
    void accept(visitor *v) override { v->visit(this); } // redundancy in my eyes!!
    // ...
};

Действительно ли мне нужно определитьчто принять функцию для каждого посетителя? Есть ли способ просто написать его один раз в базовом классе и сделать так, чтобы this ссылалось на конкретный указатель производного класса без необходимости приведения?

1 Ответ

3 голосов
/ 22 октября 2019

Что не является избыточным, это тип *this. В базовом классе тип *this равен object. В производном классе тип *this равен derived. Это различие и делает шаблон посетителей полезным.

Вы можете избежать переопределения функции во всех производных классах благодаря CRTP:

class base_acceptor{
    public:
        virtual void accept(visitor *v) {v->accept(*this);}
    };
template<class Derived, class...Bases>
class acceptor_implementer
  : public Bases...
  {
     void accept(visitor *v) override {
        assert(dynamic_cast<Derived*>(this)!=nullptr);
        v->accept(static_cast<Derived&>(*this));
        }
   };

 class acceptor1
    :acceptor_implementer<acceptor1,base_acceptor>
    {};
 class acceptor2
    :acceptor_implementer<acceptor2,base_acceptor>
    {};
 class acceptor11
    :acceptor_implementer<acceptor11,acceptor1>
    {};
...