LINUX.ORG.RU

История изменений

Исправление Miguel, (текущая версия) :

Про определение — не хочу. Определения сосут.

Про «чем не устроили» — ну, попробуй воспроизвести на C++ то, что C#/Java/Haskell/Scala делают без проблем:

using System;
interface ScalarProduct<A> {
  int scalarProduct(A second);
}
class Nil : ScalarProduct<Nil> {
  public Nil(){}
  public int scalarProduct(Nil second) {
    return 0;
  }
}
class Cons<A> : ScalarProduct<Cons<A>> where A : ScalarProduct<A> {
  public int value;
  public A tail;
  public Cons(int _value, A _tail) {
    value = _value;
    tail = _tail;
  }
  public int scalarProduct(Cons<A> second){
    return value * second.value + tail.scalarProduct(second.tail);
  }
}
class _Test{
  public static int main(int n){
    return _main(n, 0, new Nil(), new Nil());
  }
  public static int _main<A>(int n, int i, A first, A second) where A : ScalarProduct<A> {
    if (n == 0) {
      return first.scalarProduct(second);
    } else {
      return _main(n-1, i+1, new Cons<A>(2*i+1,first), new Cons<A>(i*i, second)); // Works
      //return _main(n-1, i+1, first, new Cons<A>(i*i, second)); // Doesn't work
    }
  }
}
public class Test{
  public static void Main(){
    Console.Write("Enter a number: ");
    int val = Convert.ToInt32(Console.ReadLine());
    Console.WriteLine(_Test.main(val));
  }
}

Это, конечно, высосанная из пальца задачка, но фишка в том, что невозможность сделать подобное в плюсах напрямую вытекает из того, что шаблоны — это инструмент генерации кода, а не дженерики. Отсюда и невозможность один раз откомпилировать шаблоны, а потом только использовать (Rust притворяется, что компилирует егойные «дженерики», но на самом деле просто запихивает исходный код в объектник. Ну ладно, не исходный код, а AST, но это почти одно и то же). Отсюда и километровые сообщения об ошибках, если ты используешь шаблон не так, как предполагалось. И так далее.

Что есть — так это частичная специализация, которой у настоящих дженериков нет и быть, в общем-то, не может.

Исходная версия Miguel, :

Про определение — не хочу. Определения сосут.

Про «чем не устроили» — ну, попробуй воспроизвести на C++ то, что C#/Java/Haskell/Scala делают без проблем:

[code language=csharp] using System; interface ScalarProduct<A> { int scalarProduct(A second); } class Nil : ScalarProduct<Nil> { public Nil(){} public int scalarProduct(Nil second) { return 0; } } class Cons<A> : ScalarProduct<Cons<A>> where A : ScalarProduct<A> { public int value; public A tail; public Cons(int _value, A _tail) { value = _value; tail = _tail; } public int scalarProduct(Cons<A> second){ return value * second.value + tail.scalarProduct(second.tail); } } class _Test{ public static int main(int n){ return _main(n, 0, new Nil(), new Nil()); } public static int _main<A>(int n, int i, A first, A second) where A : ScalarProduct<A> { if (n == 0) { return first.scalarProduct(second); } else { return _main(n-1, i+1, new Cons<A>(2*i+1,first), new Cons<A>(i*i, second)); // Works //return _main(n-1, i+1, first, new Cons<A>(i*i, second)); // Doesn't work } } } public class Test{ public static void Main(){ Console.Write(«Enter a number: »); int val = Convert.ToInt32(Console.ReadLine()); Console.WriteLine(_Test.main(val)); } }

Это, конечно, высосанная из пальца задачка, но фишка в том, что невозможность сделать подобное в плюсах напрямую вытекает из того, что шаблоны — это инструмент генерации кода, а не дженерики. Отсюда и невозможность один раз откомпилировать шаблоны, а потом только использовать (Rust притворяется, что компилирует егойные «дженерики», но на самом деле просто запихивает исходный код в объектник. Ну ладно, не исходный код, а AST, но это почти одно и то же). Отсюда и километровые сообщения об ошибках, если ты используешь шаблон не так, как предполагалось. И так далее.

Что есть — так это частичная специализация, которой у настоящих дженериков нет и быть, в общем-то, не может.