Шаблоны функций

Шаблоны функций создаются с использованием ключевого слова template.

После него в угловых скобках идёт список типов -- параметров шаблона.

template <typename T>
T abs(T x)
{
    static int calledTimes = 0;
    calledTimes++;
    cout << "called " << calledTimes
        << " times" << endl;
    return (x > 0) ? x : -x;
}

Использовать этот шаблон можно для разных типов, причём для каждого типа будет создана своя специализация шаблона. Мы можем это заметить по значению статической переменной, которая отслеживает сколько раз вызвана функция -- для каждой специализации это количество отслеживается отдельно.

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

int main()
{
    cout << abs(-5) << endl;
    cout << abs(-5) << endl;
    cout << abs(-5) << endl;
    cout << abs<int>(-5.6) << endl;
    cout << abs(-5.5) << endl;
    cout << abs(-5.5) << endl;
    return 0;
}

Данный шаблон может быть использован не только для стандратных, но и для пользовательских типов, поддерживающих использованные в нём операции (в данном случае -- сравнение с int и унарный минус).

class My{
    int x;
public:
    My(int _x = 0):x(_x) {}
    bool operator> (My a)
    {
        return x > a.x;
    }
    My operator-()
    {
        return My(-x);
    }
friend ostream & operator << (ostream &out, const My &r);
};
ostream & operator << (ostream &out, const My &r)
{
    out << r.x;
    return out;
}

int main()
{
    My a(-8);
    My b = abs(a);
    cout << "a = " << a << ", b = " << b << endl;
    return 0;
}