Having followed this thread for a little:
As I see it, there are several goals to be sought with header inclusions:
1) It is safe to include every header multiple times. This is not normally
a problem as include guards are now used (almost) universally.
2) It is convenient to use the functions- headers to include are obvious
in both directions. I can easily determine what header to include for a
function and can easily determine the dependencies of a module by
examining its #include directives.
3) I can cleanly replace a standard header with a custom header in order
to a) work around a bug in a system library by (e.g.) replacing a single
component from an autoconfig script and b) build custom libraries a piece
at a time, using the system libraries to supply parts that have not been
written yet.
These goals suggest the following (to me):
1) There should be one header per function or closely interrelated group
of functions. Groups of functions should be organized around a single
structure or entity (e.g. a "class" and its "methods") where this is
reasonable to do.
2) Including a header should include any sub-headers that are necessary to
process the definitions in that file. So, for instance, if a function in
an included header takes a time_t argument, it will include the
appropriate header. The headers that are allowed to be included from a
standard header should be documented with that header and standardized.
Implementations may expose less but may not expose more.
3) Whether such required definitions are visible after inclusion is
not-defined. If I need to access time_t in my own code, I need to include
the header for that type, even if a function whose definition I have
included uses time_t. This is good programming practice anyway IMHO and
makes maintenance eaiser on both sides.
4) Standard headers should take pains to not polute the namespace and to
make sure a single header can be replaced relatively independently of
other headers (idempotence?). This means limiting the number of other
headers included, using opaque types where a reference does not depend on
the size of the type being used and structuring the API to make this
easier. It also means carefully documenting the headers that are
inextricably tied together and not creating circular dependencies between
headers. Circular dependencies should generally be isolated in a single
file.
On Fri, 9 Jul 1999, Donn Terry wrote:
> Another discussion/think about item:
>
> The current POSIX indicates the inclusion of potentially
> several headers to make a given function usable. The
> draft follows the X/Open model of one header per function.
>
> There has been debate in the past on the rightness of that
> decision, but I wasn't directly involved, so I can't really
> represent either side's position accurately. I also haven't
> thought thru the implications on ISO C conformance.
>
> However, this is an issue that needs to the thought about
> in the context of POSIX, and resolved. I express no opinion
> about what the "right" answer is, just that it shouldn't
> slip through unremarked.
|