In your example you find `size_t` in the global namespace because unlike
in C, C++ standard headers are permitted to include others, and your
implementation's `<iostream>` header either directly or indirectly
includes a header such as `<stddef.h>` or `<cstddef>` that defines
`size_t` in the global namespace.
The story of the more general case of namespace pollution, including how
the “pure C++” `<cstddef>` can do that, is a bit convoluted.
For unfortunately in the original standardization of C++, in 1998, the
committee opted to innovate rather than just standardize existing
practice. They intended filename-extension-free headers such as
<iostream> to be pure C++, all in namespace `std`. And to make this so
also for the C standard library headers, most of which are available
also in the C++ standard library, they made pure C++ versions, like,
instead of dirty C global namespace stuff from `<string.h>`, you could
include `<cstring>` (no filename extension) and be happy with pure C++.
But how to implement the pure `<cstring>`? That would put a burden on
compiler vendors, who would have to do much extra work for C++. And
generally they didn't: they just made `<string.h>` C++-compatible, and
let `<cstring>` add all the global namespace identifiers to namespace
`std`. At this point, in C++98 and C++03, the FORMAL situation was that
C++03 formal:
1. The C language's `<string.h>` defines the basic contents.
2. The C++ language's `<cstring>` is defined in terms of C
`<string.h>`, but puts all identifiers in namespace `std`
instead of in the global namespace.
3. The C++ language's `<string.h>`, distinct from the C header
of the same name, is defined in terms of `<cstring>`, and
provides those identifiers in the global namespace (like the
C version of this header) but may also add them to `std`.
Since compiler vendors didn't implement things that way you couldn't
rely on it. For the in-practice it would just be stupid to rely on it.
Still, a practice of including the filename extension free headers also
for C library stuff sort of weaseled its way into being used by some. By
ignorance of the reality of implementations they made their code less
portable. E.g. inadvertent unqualified use of `strlen` could fail with
some other compiler, when that `strlen` came from `<cstring>`.
With C++11 the rules were changed to reflect the actual practice of the
compiler vendors. Which headers are defined in terms of which are the
same: there are still 3 distinct headers to consider for each C header,
e.g. the C `<string.h>`, the C++ `<cstring>`, and the C++ `<string.h>`.
But now `<cstring>` is permitted to add the identifiers to the global
namespace, just as the C++ `<string.h>` is permitted to add them to
namespace `std`.
The upshot is that now for both the in-practice and the in-formal you
have no guarantee against namespace pollution, but considering the
possibility of using others' code that includes C library headers, the
only safe recourse is to at least include the `.h` header. Possibly
include the extension-less header also to support `std::` qualification,
but at least include the `.h` header. Which will be the C++ variant of
that header, and might add the names to namespace `std`.
You can find the rules for this back in one of the appendixes to the
standard.
Cheers & hth.,
- Alf (story-teller, for the moment)