Вы не можете передавать такие типы, потому что типы не являются объектами. Они не существуют во время выполнения. Вместо этого вам нужен шаблон, который позволяет вам создавать экземпляры функций с разными типами во время компиляции:
Вы можете вызвать эту функцию, например, с помощью foo<int>(). Он создавал бы экземпляр функции с заменой T на int. Посмотрите шаблоны функций.
Ответ 2
Как отметил Джозеф Мэнсфилд, шаблон функции будет делать то, что вы хотите. В некоторых ситуациях может иметь смысл добавить параметр к функции, поэтому вам не нужно явно указывать аргумент шаблона: