Моделирование концепций C ++ с помощью свойств Scala

В документе « Классы типов как объектов и Implicits ». Я пытаюсь написать что-то вроде InputIterator концепции и find функции на Scala:

concept InputIterator<typename Iter> {
  typename value_type;
  value_type operator*(Iter);
  ...
};

template<typename Iter, typename V>
requires InputIterator<Iter> && EqualityComparable<Iter::value_type, V>
Iter find(Iter first, Iter last, V v) { 
    while (first < last && *first != v)
        ++first;
    return first;
}

Я не уверен, что правильно понимаю черты характера. Но все же ... Есть InputIterator trait, написанный на Scala (точнее - упрощенный аналог с методами, используемыми в функции find):

trait InputIterator[Iter] {
    type value_type

    def <(a: Iter, b: Iter): Boolean
    def ++(it: Iter): Unit
    def *(it: Iter): value_type
}

EqualityComparable ясно:

trait EqualityComparable[S, T] {
    def ==(s: S, t: T): Boolean
    def !=(s: S, t: T): Boolean = !(s == t)
}

Но что нам делать с find? Я хотел бы написать что-то вроде этого:

def find[Iter, V](first: Iter, last: Iter, x: V)(implicit iterator: InputIterator[Iter], 
    cmp: EqualityComparable[iterator.value_type, V]): Iter =
{
    while (iterator.<(first, last) && cmp.!=(iterator.*(first), x))
        iterator.++(first)
    first
}

Но это вызывает ошибку «недопустимый тип зависимого метода». И я не знаю, как иначе «извлечь» абстрактный тип value_type. В результате я получил такой код:

trait EqualityComparable[S, T] {
    def ==(s: S, t: T): Boolean
    def !=(s: S, t: T): Boolean = !(s == t)
}

trait InputIterator[Iter] {
    type value_type

    def <(a: Iter, b: Iter): Boolean
    def ++(it: Iter): Unit
    def *(it: Iter): value_type
}

trait VTInputIterator[Iter, VT] extends InputIterator[Iter] {
    type value_type = VT
}

class ArrayListIterator[T](a: ArrayList[T], i: Int) {
    val arr: ArrayList[T] = a
    var ind: Int = i

    def curr(): T = arr.get(ind)
    def ++(): Unit = { ind += 1 }

    override def toString() = "[" + ind.toString() + "]"
}

class InputIterArrList[T] extends VTInputIterator[ArrayListIterator[T], T]{ 
    def <(a: ArrayListIterator[T], b: ArrayListIterator[T]) = {
      if (a.arr == b.arr) a.ind < b.ind
      else throw new IllegalArgumentException()
    }

    def ++(it: ArrayListIterator[T]): Unit = it.++()
    def *(it: ArrayListIterator[T]) = it.curr()
}

object TestInputIterator extends Application{   

    def find[Iter, VT, V](first: Iter, last: Iter, x: V)(implicit iterator: VTInputIterator[Iter, VT], 
        cmp: EqualityComparable[VT, V]): Iter = 
    {
      while (iterator.<(first, last) && cmp.!=(iterator.*(first), x))
        iterator.++(first)
      first
    }

    implicit object EqIntInt extends EqualityComparable[Int, Int] {
      def ==(a: Int, b: Int): Boolean = { a == b }
    }

    implicit object inputIterArrListInt extends InputIterArrList[Int]{}

    val len = 10;
    var arr: ArrayList[Int] = new ArrayList(len);
    for (i: Int <- 1 to len)
      arr.add(i)
    var arrFirst = new ArrayListIterator(arr, 0)
    var arrLast = new ArrayListIterator(arr, len)
    var r = find(arrFirst, arrLast, 7)
    println(r)
}

Вместо абстрактного типа мы использовали параметр типа VT в def find[Iter, VT, V].

Возникает вопрос: как это можно сделать лучше? И можно ли использовать абстрактный тип value_type без дополнительного параметра типа VT?


person juliet    schedule 21.02.2013    source источник
comment
Не очень разбираюсь в C ++, так почему же InputIterator - это не просто итератор?   -  person pedrofurla    schedule 21.02.2013
comment
В C ++ Iterator - это базовый класс для итераторов, у него нет методов. А InputIterator позволяет просматривать коллекцию (только для чтения).   -  person juliet    schedule 21.02.2013


Ответы (1)


Измените подпись находки на:

def find[Iter, V, II <: InputIterator[Iter]](first: Iter, last: Iter, x: V)(
  implicit iterator: II, cmp: EqualityComparable[II#value_type, V]): Iter

Вероятно, это то, что вы хотите выразить.

Обратите внимание, что ваш код Scala на самом деле не совпадает с кодом C ++. В C ++ find используется Iter::value_type, но в Scala вы используете InputIterator[Iter]#value_type.

person Jesper Nordenberg    schedule 21.02.2013
comment
А может быть есть другие способы определения InputIterator и find? Или можно использовать только описанный выше подход? - person juliet; 21.02.2013
comment
В вашей черте InputIterator нет особого смысла, проще просто заставить итераторы расширять черту итератора. Тогда find будет выглядеть как find[Iter <: Iterator, V](first: Iter, last: Iter, x: V)(implicit cmp: EqualityComparable[Iter#value_type, V]): Iter - person Jesper Nordenberg; 21.02.2013
comment
Но таким образом мы потеряем способность к ретроактивному моделированию :( С другой стороны, это может быть не так важно в данном примере. Спасибо большое, это здорово! - person juliet; 21.02.2013