In C++, templates are a feature that supports generic programming (code that is type-independent). The template prefix is given by template <class T> (where is a type parameter that can change). The C++ Standard Template Library includes several templated classes implemented with methods for us. They vastly expand the language’s functionality.

Definitions

The interface and implementation of template definitions cannot be separated in C++ (like regular functions), so they are usually defined in header files (.hpp).

template<class T, class T2> // must be put before every function or class
void swap (T& left, T& right) {
	T temp;
	// etc
}
 
int i = 32, j = 77;
swap(i, j);
std::string s{"hi"}, t{"world"};
swap<std::string>(s, t); == swap(s, t);

Since C++20, we can use the auto parameter, which functions equivalently to the above, except that T isn’t available for us to use.

void swap(auto& left, auto& right);
swap<std::string, std::string>

Since C++14, we can allow the compiler to deduce the return type, with return type auto.

For class arguments, we don’t need to support all operations of member templates used (i.e., we can define a stack that has a print method, but it’s still useful to use for types without the output operator)

Implicit requirements

The types become clear when the generic code is used, and the compiler generally builds a new type-specific version for each type its used for. This may result in increased compilation time. The implication of this is that there are still implicit requirements when using templates:

  • All operations must be supported (i.e., operator+, operator<, copy/move constructors).
  • Sometimes we cannot deduce what kind of type we’re using. Then, the compiler can’t deduce the types. To fix this, we must explicitly state the types in our templated function call.
    • For example, we call the function once with int, int and again with int, double

The implicit requirements above are addressed with concepts (also in C++20). This formulates formal, explicit constraints for generic code.

template<typename T>
concept SupportsLessThan = requires (T x) { x < x; };
 
template <typename T>
requires std::copyable<T> && SupportsLessThan<T>
T swap(T& a, T& b);