Шаблоны - это не что иное, как макросистема. Синтаксис сахар. Они полностью раскрываются перед фактической компиляцией (или, по крайней мере, компиляторы ведут себя так, как будто это так).
Пример:
Допустим, мы хотим две функции. Одна функция берет две последовательности (список, массивы, векторы, что угодно) чисел и возвращает их внутреннее произведение. Другая функция принимает длину, генерирует две последовательности этой длины, передает их первой функции и возвращает ее результат. Уловка в том, что мы можем ошибиться во второй функции, так что эти две функции на самом деле не имеют одинаковую длину. Нам нужен компилятор, чтобы предупредить нас в этом случае. Не когда программа запущена, а когда она компилируется.
В 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 ++, и он не скомпилируется, жалуясь на бесконечное расширение шаблонов.