5 The C++ Standard specifies many mutual dependencies among the
6 headers it defines. It offers no advice on how to arrange headers
7 to avoid problems. The worst such problem is circular references.
8 Most simply this is "A includes B, B includes A":
10 // file <A> // file <B>
12 #define A 1 #define B 1
13 #include <B> #include <A>
14 typedef int A_type; typedef int B_type;
15 extern B_type g(A_type); extern A_type f(B_type);
16 #endif /* A */ #endif /* B */
21 The typical effect of such an "include loop" may be seen by tracing
22 the preprocessor activity:
35 A #ifndef A <-- oops, cpp symbol A defined already
36 A ... <-- skip <A> contents
39 B extern A_type f(B_type); <-- error, A_type not defined yet.
42 A extern B_type g(A_type);
45 The main symptom of #include loops is that definitions from file <A>
46 are not available after the #include <A> for certain include orders.
47 The number of standard headers makes testing all permutations of
48 include order impractical, so a policy is needed to prevent chaos.
49 In any case, for some standard headers (as for the above) no ordering
50 can eliminate the loop.
52 Other factors influence the policy. Typical implementations of
53 Make (unfortunately including GNU make) have bugs relating to file
54 names with no suffix, that lead to such problems as failure to track
55 dependencies on such files and an inclination to _delete_ them.
56 Therefore, headers used in building the library are always of the
57 form <bits/yyy.h> generally, or specifically <bits/std_xxx.h> for
58 an equivalent to the standard header <xxx>.
60 Standard headers <xxx> are all placed under directory std/, and
61 are ignored except during installation. These headers simply
62 #include the corresponding header <bits/std_xxx.h>.
64 Standard substitute headers <bits/std_xxx.h> that have any complexity
65 may sub-include other headers. When they sub-include non-standard
66 headers, they first include all the headers required for that
69 Mutual dependencies are handled by splitting up the declarations
70 intended for standard headers among two or more files, and then
71 interleaving them as needed. For example, we replace <A> and <B>
74 // file <bits/std_A.h>
77 # include <bits/A_types.h>
78 # include <bits/B_types.h>
79 # include <bits/A_funs.h>
82 // file <bits/std_B.h>
85 # include <bits/A_types.h>
86 # include <bits/B_types.h>
87 # include <bits/B_funs.h>
90 // file <bits/A_types.h>
91 #ifndef _CPP_BITS_A_TYPES_H
92 #define _CPP_BITS_A_TYPES_H
96 // file <bits/B_types.h>
97 #ifndef _CPP_BITS_B_TYPES_H
98 #define _CPP_BITS_B_TYPES_H
102 // file <bits/A_funs.h>
103 #ifndef _CPP_BITS_A_FUNS_H
104 #define _CPP_BITS_A_FUNS_H
105 extern B_type g(A_type);
108 // file <bits/B_funs.h>
109 #ifndef _CPP_BITS_B_FUNS_H
110 #define _CPP_BITS_B_FUNS_H
111 extern A_type f(B_type);
114 Of course we have the standard headers under their mandated names:
119 # include <bits/std_A.h>
125 # include <bits/std_B.h>
128 Notice that the include guards are named uniformly except that
129 the guard for standard header <bits/std_A.h> is just _CPP_A,
130 identically as the header <A> in std/.
132 At installation the files std/* can be replaced by symbolic links,
133 or simply copied into place as is. The result is:
136 include/A -> bits/std_A.h
137 include/B -> bits/std_A.h
141 include/bits/A_types.h
142 include/bits/B_types.h
143 include/bits/A_funs.h
144 include/bits/B_funs.h
147 Of course splitting up standard headers this way creates
148 complexity, so it is not done routinely, but only in response
151 Another reason to split up headers is for support of separate
152 compilation of templates. This interacts with the foregoing
153 because template definitions typically have many more dependencies
154 on other headers than do pure declarations. Non-inline template
155 definitions are placed in a separate ".tcc" file that is included
156 by the standard header, and any other standard header that
157 requires definitions from it for its implementation.
159 The key to preventing chaos, given the above structure, is:
161 Only standard headers <bits/std_xxxx.h> should sub-include