Каковы различия между «универсальными» типами в C ++ и Java? - PullRequest
145 голосов
/ 31 августа 2008

В Java есть дженерики, а C ++ обеспечивает очень сильную модель программирования с template s. Итак, в чем же разница между обобщениями C ++ и Java?

Ответы [ 12 ]

1 голос
/ 03 сентября 2008

@ Keith:

Этот код на самом деле неверен, и, за исключением мелких сбоев (template опущен, синтаксис специализации выглядит иначе), частичная специализация не работает с шаблонами функций, только с шаблонами классов. Код, однако, будет работать без частичной специализации шаблона, вместо этого используется простая старая перегрузка:

template <typename T> T sum(T a, T b) { return a + b; }
template <typename T> T sum(T* a, T* b) { return (*a) + (*b); }
0 голосов
/ 24 августа 2013

Шаблоны - это не что иное, как макросистема. Синтаксис сахар. Они полностью раскрываются перед фактической компиляцией (или, по крайней мере, компиляторы ведут себя так, как будто это так).

Пример:

Допустим, мы хотим две функции. Одна функция берет две последовательности (список, массивы, векторы, что угодно) чисел и возвращает их внутреннее произведение. Другая функция принимает длину, генерирует две последовательности этой длины, передает их первой функции и возвращает ее результат. Уловка в том, что мы можем ошибиться во второй функции, так что эти две функции на самом деле не имеют одинаковую длину. Нам нужен компилятор, чтобы предупредить нас в этом случае. Не когда программа запущена, а когда она компилируется.

В Java вы можете сделать что-то вроде этого:

import java.io.*;
interface ScalarProduct<A> {
    public Integer scalarProduct(A second);
}
class Nil implements ScalarProduct<Nil>{
    Nil(){}
    public Integer scalarProduct(Nil second) {
        return 0;
    }
}
class Cons<A implements ScalarProduct<A>> implements ScalarProduct<Cons<A>>{
    public Integer value;
    public A tail;
    Cons(Integer _value, A _tail) {
        value = _value;
        tail = _tail;
    }
    public Integer scalarProduct(Cons<A> second){
        return value * second.value + tail.scalarProduct(second.tail);
    }
}
class _Test{
    public static Integer main(Integer n){
        return _main(n, 0, new Nil(), new Nil());
    }
    public static <A implements ScalarProduct<A>> 
      Integer _main(Integer n, Integer i, A first, A second){
        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));
            //the following line won't compile, it produces an error:
            //return _main(n-1, i+1, first, new Cons<A>(i*i, second));
        }
    }
}
public class Test{
    public static void main(String [] args){
        System.out.print("Enter a number: ");
        try {
            BufferedReader is = 
              new BufferedReader(new InputStreamReader(System.in));
            String line = is.readLine();
            Integer val = Integer.parseInt(line);
            System.out.println(_Test.main(val));
        } catch (NumberFormatException ex) {
            System.err.println("Not a valid number");
        } catch (IOException e) {
            System.err.println("Unexpected IO ERROR");
        }
    }
}

В C # вы можете написать почти то же самое. Попробуйте переписать его на C ++, и он не скомпилируется, жалуясь на бесконечное расширение шаблонов.

...