Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Function Templates in C++: Syntax, Invocation, and Overload Resolution

Tech Jun 24 2

Function templates enable writing generic algorithms that operate on different data types without sacrificing type safety. A template declaration begins with the template keyword followed by a list of template parameters enclosed in angle brackets.

template<typename T>
void Exchange(T& first, T& second) {
    T intermediate = first;
    first = second;
    second = intermediate;
}

void DemonstrateExchange() {
    int x = 5, y = 9;
    double a = 2.3, b = 7.1;
    Exchange(x, y);               // automatic type deduction
    Exchange<int>(x, y);          // explicit type argument
    Exchange(a, b);
}

When relying on automatic deduction, all function arguments that correspond to the same template parameter must deduce the same type. If the compiler cannot deduce a consistent T, the code fails to compile. Additionally, a function template cannot be called unless every template parameter is either deduced or explicitly provided.

template<typename T>
void Swap(T& left, T& right) {
    T temp = left;
    left = right;
    right = temp;
}

template<typename T>
void Action() {
    // ...
}

void DemoConstraints() {
    int m = 1, n = 2;
    char c = 'A';
    Swap(m, n);   // OK: T deduced as int
    // Swap(m, c); // Error: cannot deduce a common T for int and char
    // Action();    // Error: T is not deducible
    Action<double>(); // OK: explicit specification
}

A template can operate on arrays. The following example implements a bubble sort algorithm for any type that supports comparison operators, together with a helper template that prints array contents.

template<typename T>
void SwapElements(T& x, T& y) {
    T tmp = x;
    x = y;
    y = tmp;
}

template<typename T>
void BubbleSort(T data[], int size) {
    for (int i = 0; i < size - 1; ++i) {
        for (int j = 0; j < size - 1 - i; ++j) {
            if (data[j] > data[j + 1]) {
                SwapElements(data[j], data[j + 1]);
            }
        }
    }
}

template<typename T>
void ShowArray(T arr[], int len) {
    for (int idx = 0; idx < len; ++idx) {
        std::cout << arr[idx] << ' ';
    }
    std::cout << std::endl;
}

void TestCharacterArray() {
    char letters[] = {'z', 'd', 'a', 'k', 'm', 'b', 'e'};
    int length = sizeof(letters) / sizeof(char);
    BubbleSort(letters, length);
    ShowArray(letters, length);
}

void TestIntegerArray() {
    int values[] = {42, 11, 74, 3, 56, 28, 19};
    int count = sizeof(values) / sizeof(int);
    BubbleSort(values, count);
    ShowArray(values, count);
}

Ordinary functions and function templates differ in how implicit conversions are handled:

  • A normal function may silently convert arguments to match paramter types.
  • A function template using automatic deduction never performs implicit conversions on the deduced template arguments.
  • When template arguments are supplied explicitly, the compiler may apply standard implicit conversions to the function parameters.
int AddIntegers(int lhs, int rhs) {
    return lhs + rhs;
}

template<typename T>
T GenericAdd(T lhs, T rhs) {
    return lhs + rhs;
}

void TestConversions() {
    int a = 20;
    char ch = 'A';      // ASCII 65
    std::cout << AddIntegers(a, ch) << std::endl;  // implicit conversion char -> int
    // std::cout << GenericAdd(a, ch);             // error: deduction conflict
    std::cout << GenericAdd<int>(a, ch) << std::endl; // explicit <int> allows conversion
}

When both a regular function and a matching template are visible, overload resolution follows these guidelines:

  • If an ordinary function provides an exact match, it is preferred over the template.
  • An empty template argument list (<>) forces the compiler to select the function template.
  • Function templates can be overloaded with different parameter sets.
  • The template wins if it yields a better match than any non-template function.
void Display(int, int) {
    std::cout << "Ordinary function called" << std::endl;
}

template<typename T>
void Display(T, T) {
    std::cout << "Function template called" << std::endl;
}

void TestOverloadResolution() {
    int u = 1, v = 2;
    Display(u, v);   // ordinary function is preferred
    Display<>(u, v); // force template instantiation

    char c1 = 'x', c2 = 'y';
    Display(c1, c2); // template gives a closer match, so template wins
}

Generic implementations may not be appropriate for every type. For example, assigning one array name to another does not copy elements, and comparing custom objects with == is unsafe unless the operator is defined. Template specialization solves this by providing tailored implementations for specific types.

class Person {
public:
    Person(const std::string& name, int age)
        : m_name(name), m_age(age) {}
    std::string m_name;
    int m_age;
};

template<typename T>
bool AreEqual(const T& a, const T& b) {
    return a == b;
}

// Explicit specialization for Person
template<>
bool AreEqual(const Person& lhs, const Person& rhs) {
    return lhs.m_name == rhs.m_name && lhs.m_age == rhs.m_age;
}

void TestComparison() {
    int i1 = 10, i2 = 10;
    std::cout << (AreEqual(i1, i2) ? "equal" : "not equal") << std::endl;

    Person alice("Alice", 30);
    Person anotherAlice("Alice", 30);
    std::cout << (AreEqual(alice, anotherAlice) ? "equal" : "not equal") << std::endl;
}
Tags: C++

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.