Я пытался перевести следующий код 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