Skip to content

Ch15: Function Templates

TL;DR: Template Blueprints: Function templates act as compiler blueprints. The compiler generates concrete function instances only for the types used in calls (instantiation).

โšก Quick Reference

#include <iostream>
#include <type_traits>
#include <cstring>

// template <typename T> - Declares a function template with type placeholder T
// T maximum(T a, T b) - Generic function template body
template <typename T>
T maximum(T a, T b) {
    return (a > b) ? a : b;
}

// template <> const char* maximum<const char*>(...) - Full specialization for const char*
template <>
const char* maximum<const char*>(const char* a, const char* b) {
    return std::strcmp(a, b) > 0 ? a : b;
}

// const T& - Passes parameters by reference to avoid copies
template <typename T>
const T& maximum_ref(const T& a, const T& b) {
    return (a > b) ? a : b;
}

// Multiple template parameters with explicit return type
template <typename ReturnType, typename T, typename P>
ReturnType mix_add(T a, P b) {
    return a + b;
}

// auto return type & trailing return type with decltype
template <typename T, typename P>
auto mix_add_deduced(T a, P b) -> decltype((a > b) ? a : b) {
    return (a > b) ? a : b;
}

// decltype(auto) - Deduces return type preserving references
template <typename T>
decltype(auto) get_ref_value(T& ref) {
    return ref;
}

// C++20 abbreviated function template using auto parameters
auto generic_auto(auto a, auto b) {
    return a + b;
}

// Non-type template parameter (NTTP)
template <typename T, size_t size>
bool is_valid(T arr[size]) {
    return size > 0;
}

int main() {
    // static_assert - Performs compile-time validation on template traits
    static_assert(std::is_integral_v<int>, "Integer required");

    // maximum<T>(a, b) - Explicitly specifies template type argument
    auto res = maximum<double>(10, 20.5);

    // if constexpr - Executes compile-time branching
    if constexpr (sizeof(int) == 4) {
        // branch compiled only if true
    }

    return 0;
}

๐Ÿง  Core Concepts

  • Template Blueprints: Function templates act as compiler blueprints. The compiler generates concrete function instances only for the types used in calls (instantiation).
  • Type Deduction & Homogeneity: The compiler automatically deduces template types, but a single template type parameter T must resolve to a single homogeneous type across all arguments.
  • Specialization & Customization: Full template specialization allows writing custom implementations for specific types (e.g., const char*) that bypass the generic blueprint.

โš ๏ธ Pitfalls (Quick Scan)

Mistake Fix
Passing conflicting argument types to a single-parameter template Provide explicit template arguments like maximum<double>(a, c)
Using unsupported operators on template type parameters inside the body Ensure type parameters support all operators used within the template body
Comparing const char values using the generic comparison template Provide a template specialization using std::strcmp for C-strings
Declaring pass-by-value and pass-by-reference overloads of the same template Stick to one parameter-passing convention, preferably const T&
Attempting to modify a template parameter passed by const T& Avoid modifying parameters declared as const references
Implicitly truncating template return types during assignment Use auto to deduce variables receiving template returns
Passing pointers to a template designed to compare values Dereference pointers at the call site or write a specialization
Relying on compilation to catch bugs in unused template parameters Instantiate templates with all supported types during testing

๐Ÿ“– Full Details

Cause โ†’ Effect โ†’ Fix with timestamp (click to expand) * **Passing conflicting argument types to a single-parameter template** -> **Compile-time error because compiler cannot resolve type placeholder `T`** -> **Provide explicit template arguments like `maximum(a, c)` (20:50)** * **Using unsupported operators on template type parameters inside the body** -> **Compile-time error stating that no matching operator exists for the type** -> **Ensure type parameters support all operators used within the template body (09:30)** * **Comparing `const char*` values using the generic comparison template** -> **Pointer addresses are compared instead of string contents, leading to bugs** -> **Provide a template specialization using `std::strcmp` for C-strings (14:30)** * **Declaring pass-by-value and pass-by-reference overloads of the same template** -> **Compile-time error because overloaded template calls become ambiguous** -> **Stick to one parameter-passing convention, preferably `const T&` (28:10)** * **Attempting to modify a template parameter passed by `const T&`** -> **Compile-time error because const references are read-only** -> **Avoid modifying parameters declared as const references (28:40)** * **Implicitly truncating template return types during assignment** -> **Silent loss of precision, such as a double converting to an int** -> **Use `auto` to deduce variables receiving template returns (07:10)** * **Passing pointers to a template designed to compare values** -> **The template compares raw memory addresses instead of dereferenced values** -> **Dereference pointers at the call site or write a specialization (14:30)** * **Relying on compilation to catch bugs in unused template parameters** -> **No code is generated for unused templates, hiding syntax errors** -> **Instantiate templates with all supported types during testing (02:22)**

๐Ÿ“Ž Repo Files

  • 24.FunctionTemplates/24.2TryingOutFunctionTemplates/main.cpp
  • 24.FunctionTemplates/24.3TemplateTypeDeductionAndExplicitArguments/main.cpp
  • 24.FunctionTemplates/24.4TemplateTypeParametersByReference/main.cpp
  • 24.FunctionTemplates/24.5TemplateSpecialization/main.cpp
  • 24.FunctionTemplates/24.6FunctionTemplatesWithOverloading/main.cpp
  • 24.FunctionTemplates/24.7FunctionTemplatesWithMultipleParameters/main.cpp
  • 24.FunctionTemplates/24.8TemplateReturnTypeDeductionWithAuto/main.cpp
  • 24.FunctionTemplates/24.9DecltypeAndTrailingReturnTypes/main.cpp
  • 24.FunctionTemplates/24.10DecltypeAuto/main.cpp
  • 24.FunctionTemplates/24.11DefaultArguments/main.cpp
  • 24.FunctionTemplates/24.12NonTypeTemplateParameters/main.cpp
  • 24.FunctionTemplates/24.13AutoFunctionTemplates/main.cpp
  • 24.FunctionTemplates/24.14NamedTemplateParametersForLambdas/main.cpp
  • 24.FunctionTemplates/24.15TypeTraits/main.cpp
  • 24.FunctionTemplates/24.16ConstexprIf/main.cpp