This is also kind of my point.
Using templates from a library and writing your own templates are two very different things.
Almost anyone of any skill can make use of templates from the standard library (e.g. std::swap
, std::min
, std::max
, std::array
, std::vector
, std::move
…),
but writing templates is something you can’t do until you can at least write functions and/or classes.
If you’re not concerned with all the ins and outs of templates then writing basic templates doesn’t take too much explaining,
but if you’re worried about things like what happens here:
int func(int)
{
return 0;
}
template<typename Type>
int func(Type)
{
return 1;
}
const int value = func(5);
Then it takes more explaining.
Most of the most common and most useful template classes and functions are already available as part of the standard library.
<algorithm>
is a header full of template functions designed for doing operations on iterators.
Some examples:
int data1[] = { 0, 1, 2, 3, 4, 5 };
int data2[6];
// Cheap and easy array copying
std::copy(std::begin(data1), std::end(data1), std::begin(data2));
// Add 1 to every element in data1
std::transform(std::begin(data1), std::end(data1), std::begin(data1), [](int value){ return (value + 1); });
// Reverse the contents of data2
std::reverse(std::begin(data2), std::end(data2));
// Create a pseudo-random number generator
std::mersenne_twiser_engine randomGenerator { /*Generate a seed somehow*/ };
// Prepare an array
unsigned int randomInts[32];
// Fill randomInts with random numbers
std::generate(std::begin(randomInts), std::end(randomInts), randomGenerator);
There’s a few useful functions that didn’t make it into the standard library until C++17.
For example std::size
to give you the size of any array or container,
and std::clamp
which is a sort of combined std::min
and std::max
.
However, those aren’t as trivial to write as you might expect.
std::clamp
has to use const
references (the same as std::min
and std::max
) for several reasons:
- Using pass-by-value could be inefficient for certain types, or even impossible for types that have disabled their copy constructors. Using a const reference allows a reference to be made to an object that can’t be copied.
- Using a non-const reference would prevent the function from accepting
const
arguments, including literal constants (e.g. integer literals), and in other cases could cause unexpected behaviour if someone tried to modify the result (e.g.++std::min(a, b);
would modify eithera
orb
).
And std::size
makes use of SFINAE and trailing return types.
At any rate, simply knowing how to write templates isn’t necessarily going to be an immediate benefit.
Templates are useful in the case that you want to write a class or function that needs to be able to operate on more than one type.
For example, if you were implementing a priority queue (since there isn’t one in the standard library) or some kind of tree and you wanted the nodes to be able to hold any type.
Or if you wanted to implement Point
s and Vector
s without constraining them to a specific numeric type, so you could have Point<int>
, Point<float>
, Vector<int>
and Vector<float>
.
None of that is the sort of thing I’d expect to see a beginner doing.