В C использовали директивы препроцессора.
#define min(x, y) ((x) < (y) ? (x) : (y))
Понятно, тут были подводные камни с побочными эффектами. И в случае ошибок диагностика компилятора была так себе. Но вообще, сишные макросы - довольно мощный аппарат, просто он не для чайников.
А взялось это всё из Лиспа, где были макросы уровня компиляции и макросы уровня чтения исходников (лексического уровня). Сишный препроцессор - как раз уровень чтения, а сиплюсплюсные шаблоны - уровень компиляции. Только в Лиспе синтаксис был один как для макросов (любого уровня), так и для исходного кода самой программы, а в C/C++ он на всех уровнях - разный.
D PМудрец (11604)
3 месяца назад
Помимо директив препроцессора надо бы еще вспомнить про использование специальных типов и типа void*, которые позволяли в какой-то мере сделать возможным передачу в одну функцию значений разных типов. Например в функции
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
в качестве указателя на структуру sockaddr* могут передаваться очень разные структуры, содержимое которых зависит от того, с каким сокетом мы хотим иметь дело