Search code examples
c++standards

Why is the C++ standard library divided into several components/libraries?


The C++ standard divides the standard library into different distinct components/libraries. Some components are built up of several headers.

Why is the standard organized in this way? What practical advantage does this bring us? Why doesn't the standard library only define headers (+ potentially implementations)?

I am assuming that this information can even be somewhat important to a C++ Dev instead of a committee member/compiler vendor, as cppreference for example often specifies from which library a given header comes from:

This header is part of the general utility library.

See here for example. Is this assumption true? If yes, when?


Solution

  • Separation of concerns, organization, etc. is already achieved with the definitions of the headers.

    Are they?

    Consider Chapter 22: Utilities. This chapter covers material defined in 13 separate headers. The standard could have had 13 separate chapters, but like... why? What good is that? Is there some reason advantage to putting all of these in separate chapters, when they'd be much shorter than most other chapters?

    Consider Chapter 31: Input/Output. This chapter covers stuff defined in 14 separate headers. But the stuff in those headers are often highly related to one another. All of the streams are ultimately built on the iostream base classes. Some of them reference things in other headers, like the ability for file streams to use filesystem::path objects.

    But they're all ultimately stuff about input/output. So it makes sense to bundle them all into one chapter.

    They could have had 14 separate chapters, one for each header, but there would be no benefit to that. Indeed, you would now have no place to put the Iostreams requirements section, which is not bound to any header at all.

    Speaking of important information that isn't bound to a header, one of the most important sections in the Container chapter is the Requirements section, which applies to every container. This section is absolutely vital for understanding anything that's happening in any of the container documentation, and in many cases defines the behavior of several functions whose definitions aren't listed in the section for those individual headers. This is because those functions behave the same way for all containers.

    I mean, do we really need to see nine separate repetitions the definitions for begin, end, etc? The whole point of the containers is to have a uniform interface so that you can understand how stuff works easily. And if you're going to have a uniform interface, repeating the definition of that interface is rather pointless.

    And then there are places where the standard can just point directly to a chapter and says, "all that stuff also has this property." The most important being the concept of freestanding implementations. Freestanding implementations are C++ implementations that don't want to implement the entire standard library because it has a lot of stuff their customers don't really need (microcontrollers don't care about filesystems, for examples). But there are parts of the standard library that must be implemented even by those systems.

    This was more prominent in pre-C++23 standards, but in many cases, the standard would just say "everything in this chapter/section must be in freestanding". That's a lot easier to do when a chapter/section can contain as many headers as it makes sense to.

    This is probably part of the reason why the Atomic chapter is not part of the Threading chapter (again, pre-C++23).

    The organization is purely for human purposes. It has no bearing on how implementations are written, outside of the freestanding stuff.