[libcxx] Which headers must include other headers?

From the C++14 spec…

17.6.5.2 Headers [res.on.headers]
1 A C++ header may include other C++ headers. A C++ header shall provide the declarations and definitions
that appear in its synopsis. A C++ header shown in its synopsis as including other C++ headers shall provide
the declarations and definitions that appear in the synopses of those other headers.

I’m not 100% sure I know what this means. If a header (say… <system_error>) mentions a class (like std::string), is it required to provide the full definition for std::string, or is the forward declared template good enough? Right now, libcxx uses the forward declaration. What about entities that have specializations scattered all over the place, like std::hash? Is the unspecialized forward declaration good enough, or does the full bulk of all the std::hash specializations have to come along too?

From the C++14 spec...

17.6.5.2 Headers [res.on.headers]
1 A C++ header may include other C++ headers. A C++ header shall provide
the declarations and definitions
that appear in its synopsis. A C++ header shown in its synopsis as
including other C++ headers shall provide
the declarations and definitions that appear in the synopses of those
other headers.

I'm not 100% sure I know what this means. If a header (say...
<system_error>) mentions a class (like std::string), is it required to
provide the full definition for std::string, or is the forward declared
template good enough?

According to the standard <system_header> does not need <string> even
though the synopsis mentions it. A forward declaration is good enough.
Although <system_header> mentions string, the synopsis for that header
doesn't declare or define std::string so [res.on.headers] doesn't apply.

Right now, libcxx uses the forward declaration. What about entities that
have specializations scattered all over the place, like std::hash? Is the
unspecialized forward declaration good enough, or does the full bulk of all
the std::hash specializations have to come along too?

I don't think all of the specialization need to come along. I'm not sure
what the QoI implications are though. Could you provide some motivation as
to why you asked this question?

My motivation is that I’m running a conformance test suite on my platform (Hexagon + libcxx + libcxxabi + modified Dinkumware C library). For the portion covering <system_error>, I get a lot of failures because the test suite tries to use / instantiate std::string, and it believes that it should be able to get the template definition transitively through <system_error>.

I like the compile time benefits of a forward string declaration, I just want to be sure it’s conformant. If not, I’m fine reporting the test as faulty.

This is a minor test suite bug. <system_error> is not required to include <string>.

There are a few instances where the standard does require one header to include another. For example <utility> is required to include <initiailizer_list>. When this is so, the synopsis of one header will have the required #include of the other header (in the standard).

There are a few places in the standard that appear to have a circular dependency among the headers. Care must be taken in the implementation to not actually create a circular dependency.

Howard

My motivation is that I'm running a conformance test suite on my platform (Hexagon + libcxx + libcxxabi + modified Dinkumware C library). For the portion covering <system_error>, I get a lot of failures because the test suite tries to use / instantiate std::string, and it believes that it should be able to get the template definition transitively through <system_error>.

I like the compile time benefits of a forward string declaration, I just want to be sure it's conformant. If not, I'm fine reporting the test as faulty.

This is a minor test suite bug. <system_error> is not required to include <string>.

There are a few instances where the standard does require one header to include another. For example <utility> is required to include <initiailizer_list>. When this is so, the synopsis of one header will have the required #include of the other header (in the standard).

Funny you should mention <utility> including <initializer_list>, because libcxx currently doesn't do that :). The test suite caught that one as well, but [res.on.headers] seems much more clear cut about that one. I plan on fixing that, but I'm still in the triage and categorization phases of running the test suite.