Templates
FAQ
-
What are C++ templates?
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 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 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:
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:
template<typename T, typename U> auto add(T a, U b) { return a + b; }This works, even with
add('A', 2);- which gives67as 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:
template<typename T> class Box { T value; };Usage of this class template might be
Box<int>orBox<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:
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 C++?
Template specialization is a feature of 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:#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:
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,UandVare 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:template<typename T, typename U, typename V> void connect(T a, U b, V c);This might be better:
template<typename SocketType, typename BufferType, typename HandlerType> void connect(SocketType socket, BufferType buffer, HandlerType handler);Notice how PascalCase and the word
Typeare used, by convention, in the type names. -
How can I use templates to implement a generic sort function in 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:
#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:
-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, andstd::spreadsortare 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.