Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Is std library allowed to pollute the global namespace?

31 views
Skip to first unread message

Shiyao Ma

unread,
Feb 15, 2017, 9:19:15 PM2/15/17
to
Hi,

I vaguely remember headers in the standard library, such as <iostream> cannot pollute the global namespace. They can only add names in the std namespace.

However, for the following code,

#include <iostream>
int main() {
size_t a;
}

The typedef of `size_t' is introduced by <iostream>.

Is this considered a violation of the language specification?

If so, where is the corresponding part in the specification?


Regards.

Alf P. Steinbach

unread,
Feb 15, 2017, 10:17:20 PM2/15/17
to
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)

Shiyao Ma

unread,
Feb 16, 2017, 5:08:19 AM2/16/17
to
A rather informative answer.

Thanks for your time.

Regards.

Cholo Lennon

unread,
Feb 16, 2017, 11:20:20 AM2/16/17
to
Adding to what others have said: maybe this will enlighten the problem,

https://developers.redhat.com/blog/2016/02/29/why-cstdlib-is-more-complicated-than-you-might-think/

Regards


--
Cholo Lennon
Bs.As.
ARG

Alf P. Steinbach

unread,
Feb 16, 2017, 11:33:30 AM2/16/17
to
Otherwise a very nice & informative article, thanks for the reference!,
but the impression it leaves that gcc's `#include_next` preprocessor
extension is needed to implement things in a reasonably practical way,
is just propaganda.

Instead of having `<cmath>` include-next the C library's `<math.h>`, as
g++ does, they could just factor out the C implementation e.g. in a
header called `<c_math_h.h>`. Then both C++ `<cmath>` and C `<math.h>`
would include `<c_math_h.h>`. It's not a problem, it's trivial.

However, such a language extension /is/ needed for practical end-user
overrides of the standard headers, that add the stuff missing in the
implementation's versions of the headers.


Cheers!,

- Alf

Tim Rentsch

unread,
Feb 17, 2017, 10:19:31 AM2/17/17
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:

> On 16.02.2017 17:20, Cholo Lennon wrote:
>> On 02/15/2017 11:18 PM, Shiyao Ma wrote:
>>> Hi,
>>>
>>> I vaguely remember headers in the standard library, such as <iostream>
>>> cannot pollute the global namespace. They can only add names in the
>>> std namespace.
>>>
>>> However, for the following code,
>>>
>>> #include <iostream>
>>> int main() {
>>> size_t a;
>>> }
>>>
>>> The typedef of `size_t' is introduced by <iostream>.
>>>
>>> Is this considered a violation of the language specification?
>>>
>>> If so, where is the corresponding part in the specification?
>>
>> Adding to what others have said: maybe this will enlighten the
>> problem,
>>
>> https://developers.redhat.com/blog/2016/02/29/
>> why-cstdlib-is-more-complicated-than-you-might-think/
>
> Otherwise a very nice & informative article, thanks for the
> reference!, but the impression it leaves that gcc's `#include_next`
> preprocessor extension is needed to implement things in a reasonably
> practical way, is just propaganda. [..alternate scheme described..]

I think the point intended is that #include_next is needed if you
want to implement a set of C++ headers on top of an existing set
of regular C headers, with the C headers being left exactly as is,
including paths and file names. I don't know if strictly speaking
this is absolutely requires something like #include_next, but I
don't see any straightforward way around it.
0 new messages