////
Copyright (c) 2024 The C++ Alliance, Inc. (https://cppalliance.org)

Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

Official repository: https://github.com/boostorg/website-v2-docs
////
= Templates
:navtitle: Templates

== FAQ

. *What are pass:[C++] templates?*
+
pass:[C++] templates are a powerful feature of the language that allows for generic programming. They enable the creation of functions or classes that can operate on different data types without having to duplicate code.

. *What are the benefits and drawbacks of using templates in pass:[C++]?*
+
The benefits of using templates include code reusability, type safety, and the ability to use generic programming paradigms. The drawbacks include more complex syntax, potentially increased compile times, difficult-to-understand error messages, and other complexities associated with template metaprogramming.

. *What are function templates in pass:[C++]?*
+
Function templates are functions that can be used with any data type. You define them using the keyword template followed by the template parameters. Function templates allow you to create a single function that can operate on different data types, for example:
+
[source,cpp]
----
template<typename T>
T add(T a, T b)
{
    return a + b;
}
----
+
This will work if both types of the input are the same (ints, floats, chars even). If you want to add two different types together, then use:
+
[source,cpp]
----
template<typename T, typename U>
auto add(T a, U b)
{
    return a + b;
}
----
This works, even with `add('A', 2);` - which gives `67` as a result.

. *Apart from function templates, are there other types of templates?*
+
Yes, there are many other types of template, including class templates that define generic object types or data structures. For example:
+
[source,cpp]
----
template<typename T>
class Box
{
    T value;
};
----
+
Usage of this class template might be `Box<int>` or `Box<double>`. Class templates usually require explicit type declaration, whereas function templates usually let the compiler infer the type.
+
Whereas function and class templates are the most used, the following table shows how many types of template there are now:
+
[cols="1,1",stripes=even,options="header",frame=none]
|===
| *Template Type*               | *Purpose*              
| Function Template           | Generic algorithms                
| Class Template              | Generic objects/data structures   
| Variable Template           | Generic constants/variables       
| Alias Template              | Generic type aliases              
| Member Function Template    | Generic methods inside classes    
| Template Template Parameter | Templates that accept templates   
| Non-Type Template           | Compile-time values as parameters 
| Constrained Template        | Restrict allowed template types   
| Lambda Template             | Generic anonymous functions       
| Metaprogramming Template    | Compile-time computation          
|===
+
For more details on using these template types refer to the documentation for boost:mp11[] and boost:hana[].

. *What is template specialization in pass:[C++]?*
+
Template specialization is a feature of pass:[C++] templates that allows you to define a different implementation of a template for a specific type or set of types. It can be used with both class and function templates. For example, the following code shows a specialization template for `bool`, which we want to handle differently:
+
[source,cpp]
----
#include <iostream>

// Primary template
template<typename T>
void print(T value)
{
    std::cout << "Generic: " << value << "\n";
}

// Specialization for bool
template<>
void print<bool>(bool value)
{
    std::cout
        << "Boolean: "
        << (value ? "true" : "false")
        << "\n";
}

int main()
{
    print(42);
    print(3.14);
    print(true);
    print(false);
}
----
+
Run this code and you will see the difference:
+
[source,text]
----
Generic: 42
Generic: 3.14
Boolean: true
Boolean: false
----

. *What is considered good practice for naming template types - I see "T" and "U" often used for example - is this considered explicit enough?*
+
`T`, `U` and `V` are traditional and perfectly acceptable for small, obvious templates, and usually used in that order for first, second and third template type. But for more complex code, descriptive names are usually better. For example the following code is not that helpful:
+
[source,cpp]
----
template<typename T,
         typename U,
         typename V>
void connect(T a, U b, V c);
----
+
This might be better:
+
[source,cpp]
----
template<typename SocketType,
         typename BufferType,
         typename HandlerType>
void connect(SocketType socket,
             BufferType buffer,
             HandlerType handler);
----
+
Notice how PascalCase and the word `Type` are used, by convention, in the type names.


. *How can I use templates to implement a generic sort function in pass:[C++]?*
+
Here's an example of how you might use a function template to implement a generic sort function, working with boost:range[], so any type that is supported by this library can be sorted using the following function:
+
[source,cpp]
----
#include <boost/range/iterator_range.hpp>

// Bubble sort using Boost.Range-compatible interface
template<typename Range>
void bubble_sort_range(Range& r) {
    using std::begin;
    using std::end;

    using Iterator = typename boost::range_iterator<Range>::type;
    using Category = typename std::iterator_traits<Iterator>::iterator_category;

    // Enforce random access iterators at compile time
    BOOST_STATIC_ASSERT((std::is_base_of<std::random_access_iterator_tag, Category>::value));

    Iterator first = boost::begin(r);
    Iterator last = boost::end(r);

    if (first == last) return;

    bool swapped = true;
    while (swapped) {
        swapped = false;
        for (Iterator it = first; it + 1 != last; ++it) {
            if (*(it + 1) < *it) {
                std::iter_swap(it, it + 1);
                swapped = true;
            }
        }
        --last;
    }
}

// Usage example:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> nums = { 9, 3, 7, 1, 4, 6, 12, 21, 14, 13, 11, 9, -1, -4 };
    bubble_sort_range(nums);

    for (int n : nums)
        std::cout << n << " ";
    std::cout << "\n";

    std::vector<std::string> names = { "charlie", "alice", "bob", "pete", "vanessa", "dave", "alexi"};
    bubble_sort_range(names);

    for (const auto& name : names)
        std::cout << name << " ";
    std::cout << "\n";
}

----
+
Running the example you should get the output:
+
[source,text]
----
-4 -1 1 3 4 6 7 9 9 11 12 13 14 21
alexi alice bob charlie dave pete vanessa

----

Note:: The use of templates for sorting is given as an example only, the `std::sort`, `std::stable_sort`, and `std::spreadsort` are super efficient and should be used whenever possible. However, if you have a special process you would like to apply to different types of ranges, this templated approach may work well for you. For specialized sorts, refer to boost:sort[].

== See Also

* xref:faq.adoc[]