Chapter 15: Function Overloading and Templates

Function Overloading

Function overloading allows you to define multiple functions with the same name but different parameters.

Example

int add(int x, int y) // integer version
{
    return x + y;
}

double add(double x, double y) // floating point version
{
    return x + y;
}

Overload Resolution

Overload resolution is the process of determining which overloaded function to call based on the arguments provided.

void deg_min_sec2decimal(double deg, double min, double sec, double& dec_deg)
{
    dec_deg = (deg + min / 60.0 + sec / 3600.0);
}

foo(0); // int can be numerically converted to unsigned int or to float
foo(3.14159); // double can be numerically converted to unsigned int or to float
// ambiguous result causes error

Deleted Functions

You can delete specific overloads to prevent them from being used.

void printInt(char) = delete; // calls to this function will halt compilation
void printInt(bool) = delete; // calls to this function will halt compilation

template <typename T>
void printInt(T x) = delete;

void printInt(int x)
{
    std::cout << x << '\n';
}

printInt(97);   // okay
printInt('a');  // compile error
printInt(true); // compile error

Default Arguments

Functions can have parameters with default arguments.

void print(int x, int y = 10) // 10 is the default argument
{
    std::cout << "x: " << x << '\n';
    std::cout << "y: " << y << '\n';
}

print(1, 2); // y will use user-supplied argument 2
print(3);    // y will use default argument 10

Note: If a parameter is given a default argument, all subsequent parameters must also be given default arguments.

Header File Example

#ifndef FOO_H
#define FOO_H
void print(int x, int y = 4);
#endif

Templates

Function Templates

template <typename T> // this is the template parameter declaration
T max(T x, T y) // this is the function template definition for max<T>
{
    return (x < y) ? y : x;
}

std::cout << max<int>(1, 2) << '\n'; // calls max<int>(int, int)
std::cout << max<>(1, 2) << '\n';    // deduces max<int>(int, int)
std::cout << max(1, 2) << '\n';      // calls max(int, int)

template <typename T>
int someFcn(T, double){} // Template parameter and double

Template Example in Header File

#ifndef ADD_H
#define ADD_H

template <typename T>
T addOne(T x) // function template definition
{
    return x + 1;
}

#endif

Auto Templates (C++20)

auto max(auto x, auto y)
{
    return (x < y) ? y : x;
}

Non-Type Template Parameters

#include <iostream>

template <int N> // declare a non-type template parameter of type int named N
void print()
{
    std::cout << N << '\n'; // use value of N here
}

print<5>(); // 5 is our non-type template argument

Class Templates

template <typename T>
struct Pair
{
    T first{};
    T second{};
};

template <typename T>
constexpr T max(Pair<T> p)
{
    return (p.first < p.second ? p.second : p.first);
}

Pair<int> p1{ 5, 6 };
Pair<double> p2{ 1.2, 3.4 };

std::cout << max(p2) << '\n'; // call to max<double> using template argument deduction
std::cout << max<int>(p1) << '\n'; // explicit call to max<int>

Class Template with Multiple Types

template <typename T, typename U>
struct Pair
{
    T first{};
    U second{};
};

template <typename T, typename U>
void print(Pair<T, U> p)
{
    std::cout << '[' << p.first << ", " << p.second << ']';
}

Pair<int, double> p1{ 1, 2.3 }; // a pair holding an int and a double
print(p1);

Class Template Argument Deduction (CTAD)

#include <utility> // for std::pair

std::pair p1{ 1, 2 }; // CTAD used to deduce std::pair<int, int> from the initializers (C++17)

std::pair p2 { 3.4f, 5.6f }; // deduced to pair<float, float>
std::pair p3 { 1u, 2u };     // deduced to pair<unsigned int, unsigned int>
Pair p4;                     // uses default Pair<int, int>

Alias Templates

template <typename T>
using Coord = Pair<T>; // Coord is an alias for Pair<T>

Coord<int> p1 { 1, 2 };     // Pre C++-20: We must explicitly specify all type template arguments
Coord p2 { 1, 2 };          // In C++20, we can use alias template deduction to deduce the template arguments in cases where CTAD works

Deduction Guide

// Here's a deduction guide for our Pair (needed in C++17 only)
template <typename T, typename U>
Pair(T, U) -> Pair<T, U>;