This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of CD1 status.

### 456. Traditional C header files are overspecified

Section: 16.4.2.3 [headers] Status: CD1 Submitter: Bill Plauger Opened: 2004-01-30 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [headers].

View all issues with CD1 status.

Discussion:

The C++ Standard effectively requires that the traditional C headers (of the form <xxx.h>) be defined in terms of the newer C++ headers (of the form <cxxx>). Clauses 17.4.1.2/4 and D.5 combine to require that:

- Including the header <cxxx> declares a C name in namespace std.
- Including the header <xxx.h> declares a C name in namespace std (effectively by including <cxxx>), then imports it into the global namespace with an individual using declaration.

The rules were left in this form despited repeated and heated objections from several compiler vendors. The C headers are often beyond the direct control of C++ implementors. In some organizations, it's all they can do to get a few #ifdef __cplusplus tests added. Third-party library vendors can perhaps wrap the C headers. But neither of these approaches supports the drastic restructuring required by the C++ Standard. As a result, it is still widespread practice to ignore this conformance requirement, nearly seven years after the committee last debated this topic. Instead, what is often implemented is:

- Including the header <xxx.h> declares a C name in the global namespace.
- Including the header <cxxx> declares a C name in the global namespace (effectively by including <xxx.h>), then imports it into namespace std with an individual using declaration.

The practical benefit for implementors with the second approach is that they can use existing C library headers, as they are pretty much obliged to do. The practical cost for programmers facing a mix of implementations is that they have to assume weaker rules:

- If you want to assuredly declare a C name in the global namespace, include <xxx.h>. You may or may not also get the declaration in namespace std.
- If you want to assuredly declare a C name in namespace std, include <cxxx>. You may or may not also get the declaration in the global namespace.

There also exists the possibility of subtle differences due to Koenig lookup, but there are so few non-builtin types defined in the C headers that I've yet to see an example of any real problems in this area.

It is worth observing that the rate at which programmers fall afoul of these differences has remained small, at least as measured by newsgroup postings and our own bug reports. (By an overwhelming margin, the commonest problem is still that programmers include <string> and can't understand why the typename string isn't defined -- this a decade after the committee invented namespace std, nominally for the benefit of all programmers.)

We should accept the fact that we made a serious mistake and rectify it, however belatedly, by explicitly allowing either of the two schemes for declaring C names in headers.

[Sydney: This issue has been debated many times, and will certainly have to be discussed in full committee before any action can be taken. However, the preliminary sentiment of the LWG was in favor of the change. (6 yes, 0 no, 2 abstain) Robert Klarer suggests that we might also want to undeprecate the C-style `.h` headers.]

Proposed resolution:

Add to 16.4.2.3 [headers], para. 4:

> Except as noted in clauses 18 through 27 and Annex D, the contents of each header cname shall be the same as that of the corresponding header name.h, as specified in ISO/IEC 9899:1990 Programming Languages C (Clause 7), or ISO/IEC:1990 Programming Languages-C AMENDMENT 1: C Integrity, (Clause 7), as appropriate, as if by inclusion. In the C++ Standard Library, however, the declarations and definitions (except for names which are defined as macros in C) are within namespace scope (3.3.5) of the namespace std. It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations (9.9 [namespace.udecl]).

Change 99 [depr.c.headers], para. 2-3:

> -2- Every C header, each of which has a name of the form name.h, behaves as if each name placed in the Standard library namespace by the corresponding cname header is also placed within the global namespace scope. of the namespace `std` and is followed by an explicit using-declaration (9.9 [namespace.udecl]). It is unspecified whether these names are first declared or defined within namespace scope (6.4.5 [basic.scope.namespace]) of the namespace `std` and are then injected into the global namespace scope by explicit using-declarations (9.9 [namespace.udecl]).

> -3- [Example: The header `<cstdlib>` assuredly provides its declarations and definitions within the namespace `std`. It may also provide these names within the global namespace. The header `<stdlib.h>` makes these available also in assuredly provides the same declarations and definitions within the global namespace, much as in the C Standard. It may also provide these names within the namespace `std`. -- end example]