Возможен ли шаблон посетителя без состояния в C ++?

Я пытался перевести следующий код Haskell на C ++:

data List t = Nil | Cons t (List t)

Прямой перевод алгебраического типа данных в шаблон посетителя без сохранения состояния дает следующий код Java

interface List {
   R accept(ListVisitor v);
}

interface ListVisitor {
  R visitNil();
  R visitCons(T head, List tail);
}

class Nil implements List {
  @Override
  public  R accept(ListVisitor v) {
    return v.visitNil();
  }
}

class Cons implements List {
  public final T head;
  public final List tail;
  public Cons(T head, List tail) {
    this.head = head;
    this.tail = tail;
  }
  @Override
  public  R accept(ListVisitor v) {
    return v.visitCons(head, tail);
  }
}

Ниже приведен код C ++, который у меня есть:

template class List;

template class ListVisitor {
  virtual R visitNil() = 0;
  virtual R visitCons(T head, List tail) = 0;
};

template class List {
  template virtual R accept(ListVisitor v) = 0;
};

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

Есть ли другое решение, кроме как заставить accept return void и требовать от посетителей сохранения состояния?

Обновление: По запросу, вот несколько примеров использования интерфейсов (интеллектуальные указатели по модулю и возможные ошибки компиляции):

template struct LengthVisitor : ListVisitor {
  bool visitNil() { return 0; }
  bool visitCons(const T&, const List &tail) { return 1 + tail.accept(*this); }
};

template struct ConcatVisitor : ListVisitor *> {
  const List *right;
  ConcatVisitor(const List *right) : right(right) {} 
  List * visitNil() { return right; }
  List * visitCons(const T &head, const List & tail) {
    return new Cons(head, tail.accept(*this));
  }
};

Другой пример, функция более высокого уровня fold в Java, можно найти здесь: http://hpaste.org/54650

11
задан Dave Schweisguth 14 February 2016 в 00:03
поделиться