+++ /dev/null
-
-Header Policy
--------------
-
-The C++ Standard specifies many mutual dependencies among the
-headers it defines. It offers no advice on how to arrange headers
-to avoid problems. The worst such problem is circular references.
-Most simply this is "A includes B, B includes A":
-
- // file <A> // file <B>
- #ifndef A #ifndef B
- #define A 1 #define B 1
- #include <B> #include <A>
- typedef int A_type; typedef int B_type;
- extern B_type g(A_type); extern A_type f(B_type);
- #endif /* A */ #endif /* B */
-
- // file C.cc
- #include <A>
-
-The typical effect of such an "include loop" may be seen by tracing
-the preprocessor activity:
-
- C // file C.cc
- C #include <A>
- A // file <A>
- A #ifndef A
- A #define A 1
- A #include <B>
- B // file <B>
- B #ifndef B
- B #define B 1
- B #include <A>
- A // file <A>
- A #ifndef A <-- oops, cpp symbol A defined already
- A ... <-- skip <A> contents
- A #endif
- B typedef int B_type;
- B extern A_type f(B_type); <-- error, A_type not defined yet.
- B #endif /* B */
- A typedef int A_type;
- A extern B_type g(A_type);
- A #endif /* A */
-
-The main symptom of #include loops is that definitions from file <A>
-are not available after the #include <A> for certain include orders.
-The number of standard headers makes testing all permutations of
-include order impractical, so a policy is needed to prevent chaos.
-In any case, for some standard headers (as for the above) no ordering
-can eliminate the loop.
-
-Other factors influence the policy. Typical implementations of
-Make (unfortunately including GNU make) have bugs relating to file
-names with no suffix, that lead to such problems as failure to track
-dependencies on such files and an inclination to _delete_ them.
-Therefore, headers used in building the library are always of the
-form <bits/yyy.h> generally, or specifically <bits/std_xxx.h> for
-an equivalent to the standard header <xxx>.
-
-Standard headers <xxx> are all placed under directory std/, and
-are ignored except during installation. These headers simply
-#include the corresponding header <bits/std_xxx.h>.
-
-Standard substitute headers <bits/std_xxx.h> that have any complexity
-may sub-include other headers. When they sub-include non-standard
-headers, they first include all the headers required for that
-non-standard header.
-
-Mutual dependencies are handled by splitting up the declarations
-intended for standard headers among two or more files, and then
-interleaving them as needed. For example, we replace <A> and <B>
-above, as follows:
-
- // file <bits/std_A.h>
- #ifndef _CPP_A
- #define _CPP_A
- # include <bits/A_types.h>
- # include <bits/B_types.h>
- # include <bits/A_funs.h>
- #endif
-
- // file <bits/std_B.h>
- #ifndef _CPP_B
- #define _CPP_B
- # include <bits/A_types.h>
- # include <bits/B_types.h>
- # include <bits/B_funs.h>
- #endif
-
- // file <bits/A_types.h>
- #ifndef _CPP_BITS_A_TYPES_H
- #define _CPP_BITS_A_TYPES_H
- typedef int A_type;
- #endif
-
- // file <bits/B_types.h>
- #ifndef _CPP_BITS_B_TYPES_H
- #define _CPP_BITS_B_TYPES_H
- typedef int B_type;
- #endif
-
- // file <bits/A_funs.h>
- #ifndef _CPP_BITS_A_FUNS_H
- #define _CPP_BITS_A_FUNS_H
- extern B_type g(A_type);
- #endif
-
- // file <bits/B_funs.h>
- #ifndef _CPP_BITS_B_FUNS_H
- #define _CPP_BITS_B_FUNS_H
- extern A_type f(B_type);
- #endif
-
-Of course we have the standard headers under their mandated names:
-
- // file <std/A>
- #ifndef _CPP_A
- #define _CPP_A
- # include <bits/std_A.h>
- #endif
-
- // file <std/B>
- #ifndef _CPP_B
- #define _CPP_B
- # include <bits/std_B.h>
- #endif
-
-Notice that the include guards are named uniformly except that
-the guard for standard header <bits/std_A.h> is just _CPP_A,
-identically as the header <A> in std/.
-
-At installation the files std/* can be replaced by symbolic links,
-or simply copied into place as is. The result is:
-
- include/
- include/A -> bits/std_A.h
- include/B -> bits/std_A.h
- include/bits/
- include/bits/std_A.h
- include/bits/std_B.h
- include/bits/A_types.h
- include/bits/B_types.h
- include/bits/A_funs.h
- include/bits/B_funs.h
-
-
-Of course splitting up standard headers this way creates
-complexity, so it is not done routinely, but only in response
-to discovered needs.
-
-Another reason to split up headers is for support of separate
-compilation of templates. This interacts with the foregoing
-because template definitions typically have many more dependencies
-on other headers than do pure declarations. Non-inline template
-definitions are placed in a separate ".tcc" file that is included
-by the standard header, and any other standard header that
-requires definitions from it for its implementation.
-
-The key to preventing chaos, given the above structure, is:
-
- Only standard headers <bits/std_xxxx.h> should sub-include
- other headers.
-
-