Section: 16 [library] Status: Resolved Submitter: Martin Sebor Opened: 2001-10-09 Last modified: 2016-01-28
Priority: Not Prioritized
View other active issues in [library].
View all other issues in [library].
View all issues with Resolved status.
Discussion:
The synopses of the C++ library headers clearly show which names are required to be defined in each header. Since in order to implement the classes and templates defined in these headers declarations of other templates (but not necessarily their definitions) are typically necessary the standard in 17.4.4, p1 permits library implementers to include any headers needed to implement the definitions in each header.
For instance, although it is not explicitly specified in the synopsis of
<string>
, at the point of definition of the std::basic_string
template
the declaration of the std::allocator
template must be in scope. All
current implementations simply include <memory>
from within <string>
,
either directly or indirectly, to bring the declaration of
std::allocator
into scope.
Additionally, however, some implementation also include <istream>
and
<ostream>
at the top of <string>
to bring the declarations of
std::basic_istream
and std::basic_ostream
into scope (which are needed
in order to implement the string inserter and extractor operators
(21.3.7.9 [lib.string.io])). Other implementations only include
<iosfwd>
, since strictly speaking, only the declarations and not the
full definitions are necessary.
Obviously, it is possible to implement <string>
without actually
providing the full definitions of all the templates std::basic_string
uses (std::allocator
, std::basic_istream
, and std::basic_ostream
).
Furthermore, not only is it possible, doing so is likely to have a
positive effect on compile-time efficiency.
But while it may seem perfectly reasonable to expect a program that uses
the std::basic_string
insertion and extraction operators to also
explicitly include <istream>
or <ostream>
, respectively, it doesn't seem
reasonable to also expect it to explicitly include <memory>
. Since
what's reasonable and what isn't is highly subjective one would expect
the standard to specify what can and what cannot be assumed.
Unfortunately, that isn't the case.
The examples below demonstrate the issue.
Example 1:
It is not clear whether the following program is complete:
#include <string> extern std::basic_ostream<char> &strm; int main () { strm << std::string ("Hello, World!\n"); }
or whether one must explicitly include <memory>
or
<ostream>
(or both) in addition to <string>
in order for
the program to compile.
Example 2:
Similarly, it is unclear whether the following program is complete:
#include <istream> extern std::basic_iostream<char> &strm; int main () { strm << "Hello, World!\n"; }
or whether one needs to explicitly include <ostream>
, and
perhaps even other headers containing the definitions of other
required templates:
#include <ios> #include <istream> #include <ostream> #include <streambuf> extern std::basic_iostream<char> &strm; int main () { strm << "Hello, World!\n"; }
Example 3:
Likewise, it seems unclear whether the program below is complete:
#include <iterator> bool foo (std::istream_iterator<int> a, std::istream_iterator<int> b) { return a == b; } int main () { }
or whether one should be required to include <istream>
.
There are many more examples that demonstrate this lack of a requirement. I believe that in a good number of cases it would be unreasonable to require that a program explicitly include all the headers necessary for a particular template to be specialized, but I think that there are cases such as some of those above where it would be desirable to allow implementations to include only as much as necessary and not more.
[ post Bellevue: ]
Position taken in prior reviews is that the idea of a table of header dependencies is a good one. Our view is that a full paper is needed to do justice to this, and we've made that recommendation to the issue author.
[ 2009-07 Frankfurt ]
Resolved. Handled by LWG 1178.
Proposed resolution:
For every C++ library header, supply a minimum set of other C++ library headers that are required to be included by that header. The proposed list is below (C++ headers for C Library Facilities, table 12 in 17.4.1.2, p3, are omitted):
+------------+--------------------+ | C++ header |required to include | +============+====================+ |<algorithm> | | +------------+--------------------+ |<bitset> | | +------------+--------------------+ |<complex> | | +------------+--------------------+ |<deque> |<memory> | +------------+--------------------+ |<exception> | | +------------+--------------------+ |<fstream> |<ios> | +------------+--------------------+ |<functional>| | +------------+--------------------+ |<iomanip> |<ios> | +------------+--------------------+ |<ios> |<streambuf> | +------------+--------------------+ |<iosfwd> | | +------------+--------------------+ |<iostream> |<istream>, <ostream>| +------------+--------------------+ |<istream> |<ios> | +------------+--------------------+ |<iterator> | | +------------+--------------------+ |<limits> | | +------------+--------------------+ |<list> |<memory> | +------------+--------------------+ |<locale> | | +------------+--------------------+ |<map> |<memory> | +------------+--------------------+ |<memory> | | +------------+--------------------+ |<new> |<exception> | +------------+--------------------+ |<numeric> | | +------------+--------------------+ |<ostream> |<ios> | +------------+--------------------+ |<queue> |<deque> | +------------+--------------------+ |<set> |<memory> | +------------+--------------------+ |<sstream> |<ios>, <string> | +------------+--------------------+ |<stack> |<deque> | +------------+--------------------+ |<stdexcept> | | +------------+--------------------+ |<streambuf> |<ios> | +------------+--------------------+ |<string> |<memory> | +------------+--------------------+ |<strstream> | | +------------+--------------------+ |<typeinfo> |<exception> | +------------+--------------------+ |<utility> | | +------------+--------------------+ |<valarray> | | +------------+--------------------+ |<vector> |<memory> | +------------+--------------------+
Rationale:
The portability problem is real. A program that works correctly on one implementation might fail on another, because of different header dependencies. This problem was understood before the standard was completed, and it was a conscious design choice.
One possible way to deal with this, as a library extension, would
be an <all>
header.
Hinnant: It's time we dealt with this issue for C++0X. Reopened.