The C++ Standard Library Headers
The <numeric> library in C++ provides a small set of generalized numerical algorithms.
Why Programs Keep Needing the Same Arithmetic
Many programs need to do arithmetic over collections of values. They add up a list of numbers, combine results step by step, or process a sequence of data. You could write a fresh loop for each of these jobs every time, but C++ does not require that. The standard library collects a set of ready-made routines for these jobs, and the header named <numeric> is where a group of them lives.
What do you think happens?
Suppose a list holds the values 1, 2, 3 and 4, and you want one number that represents their total. Before reading on, what single number do you expect a summing routine to return?
Reveal answer
10
Adding 1, 2, 3 and 4 gives 10. The routine described in this article, accumulate(), is one way the <numeric> library performs this kind of combining, and the next section traces how it reaches that total one element at a time.
The idea of this article is simple. Before you write numerical code, you should first ask whether the standard library already provides a routine for it. The <numeric> header is the first place to check, and the rest of this article shows how to reason about where a routine lives.
Tracing a Running Total Through accumulate()
accumulate() is named in the source as an example of a numerical algorithm found in <numeric>. The best way to understand what it does is to watch it work on a small collection. The program below stores four values in a vector and asks accumulate() to combine them into one total. The third argument, 0, is the starting value that the running total begins from.
10- #include <numeric> brings in the header that supplies
accumulate() - std::accumulate uses the std:: prefix because the declaration lives in namespace std
scores.begin()andscores.end()mark the range of values to combine
Read the diagram from left to right. accumulate() begins with the starting value 0. It then combines that running total with the first element, producing 1. It combines the new running total with the second element, producing 3. Then it adds the third element to get 6, and finally the fourth element to get 10. The routine does not jump straight to the answer. It carries a running total forward, one element at a time, and the last value of that total is what the call returns.
What Makes a Numerical Algorithm Generalized
Generalized numerical algorithms are reusable, general-purpose routines for numerical work rather than one-off code. The <numeric> library in C++ provides a small set of them.
The word generalized is the key idea. A one-off routine solves one specific problem, such as adding the four numbers in one particular list. A generalized routine is written so that the same logic can be applied to many different collections of values. The accumulate() call in the previous section does not care that the numbers happen to be 1, 2, 3 and 4. You can point it at a different range of values and it performs the same combining process on that range.
The source describes the <numeric> set as small and focused. It is not an exhaustive catalogue of every mathematical operation. This matters when you approach a new numerical task. Checking <numeric> is a sensible first step, but if the routine you need is not there, that does not mean the standard library has nothing for you. It means you should keep looking through the listing for the family of tools that fits your task.
Finding Which Header Supplies a Name
A Standard Library header is a header file that supplies declarations for a particular kind of functionality, such as containers, algorithms, or utilities. The word declarations means the names and interfaces of the classes and functions the header offers. When you need a feature, you look up the header that carries its declaration, and then you include that header in your program.
The reasoning runs from the library down to the name. accumulate() is an example of a numerical algorithm, numerical algorithms belong to the <numeric> library, and so the header to include is <numeric>. You can trace the same chain for any name that the selected listing covers. This approach asks you to understand where a routine belongs, rather than to memorize every name in isolation.
The listing sorts its rows into three families that appear throughout the listing. Containers include array, vector, forward_list, map, set, and the unordered variants. Algorithms include sort(), find(), and copy(). Utilities include pair, move(), and swap(). Other headers cover input and output, strings, regular expressions, time, random numbers, threads, and file streams. This grouping is a reading aid. The source does not state it as a formal category system, but it helps you narrow down where to look.
The std Namespace and the std:: Prefix
Every header in the selected listing supplies its declarations in namespace std. A namespace is a named scope that groups related names, and std is the namespace where the Standard Library defines its declarations. This is why library names are written with the std:: prefix, as in std::copy(), std::find(), and std::sort(). The same rule applies to the accumulate() call in the earlier example, which is written as std::accumulate.
Read the diagram as two relationships. The header supplies declarations, and those declarations belong to std. The header is the place you include in your file. The namespace is the place where the name lives, and it is why your code writes the qualified name with the prefix.
Mistakes Learners Make with Headers and Names
Common mistake Treating the listing as a complete reference
What it looks likeDeciding that a routine does not exist because it is missing from the selected listing.
Why it failsThe source states that the listing is far from complete and works as a starting map, not a full reference.
Do this insteadUse the listing to find the family and header that fit your task, then check the wider library for anything not shown.
Common mistake Leaving off the std:: prefix
What it looks likeWriting accumulate(scores.begin(), scores.end(), 0) without qualifying the name.
Why it failsLibrary declarations are defined in namespace std, so the name is referenced through that scope.
Do this insteadWrite std::accumulate, as in the example in this article.
Common mistake Confusing a header with a single function
What it looks likeThinking that <numeric> is only accumulate() and that it contains nothing else.
Why it failsA header supplies a group of declarations for a kind of functionality.
accumulate()is one named member of the numerical group.Do this insteadThink of a header as a grouping by purpose, and look at what else the group offers.
Common mistake Assuming a routine must be written from scratch before checking the standard library
Practice: Locating a Routine from Its Role
A colleague wants to add up the values stored in a vector of prices. Using only the reasoning in this article, name the header you would include to find a ready-made routine for this job, and write the qualified name you would use to call it.
Hints
- Ask which library the routine belongs to, given that it combines a collection of values into one number.
- Remember that
accumulate()is named as a numerical algorithm in the <numeric> library. - Library names are written with the std:: prefix.
Key Takeaways
- The <numeric> header supplies a small, focused set of generalized numerical algorithms, reusable routines for numerical work rather than one-off code.
accumulate()is named as one numerical algorithm in <numeric>, and it combines a range of values step by step into a running total.- A Standard Library header supplies declarations for a kind of functionality, and you locate a name by reasoning from its library and role.
- Every header in the selected listing supplies declarations in namespace std, which is why library names are written with the std:: prefix.
- The listing is a starting map, not a complete reference, so use it to narrow down where to look.