
Hervé Brönnimann wrote:
On Nov 20, 2006, at 7:48 AM, John Maddock wrote:
I think the problem here is that it's tricky to ensure that you have all the necessary headers included: different implementations may or may not flag up an error depending which headers you've included, so including <iostream> is a sort of "belt-and-braces" approach.
The local fix for this is to write a library's cpp file that get compiled into the library.h, whose first line is #include "filename.h". This ensures that all the right headers get pulled in properly. In fact, the standard practice is to always include the headers in *reverse* order of dependency. The same works for the test driver: there is one test file dedicated simply to make sure that #include "filename.h" works without including anything else. It's a bit of a discipline and one must make sure that all code template has been instantiated, so it (like anything else) is not foolproof. You also need a notion of physical dependency and hierarchy levels. For this, I refer to John Lakos' book (whose second edition is in the writing).
Absolutely, but that still only ensures that filename.hpp compiles cleanly with your specific compiler / std lib combination: many std lib's will pull in code that isn't actually needed according to the std. For example does this compile: #include <stdexcept> std::domain_error d("abc"); You may think "yes" because domain_error is defined in the header included, however the constructor relies on std::string being fully defined, but <stdexcept> need only forward declare std::string to make itself work. There is one lib (STLPort) that actually does it this way too: the rationale, is that you can do things like: #include <stdexcept> void print_message(const char*); int foo() { try{ //something }catch(const std::domain_error& e) { print_message(e.what()); } } without requiring all of <string>. In practice though most other std lib's do include <string> implicitly when you include <stdexcept>. As far as I know there is no concensus on the committee on whether this should work or not. Frankly, it's one of those bicycle-shed discussion items :-( It's also why as things stand, if you want to know whether you have included all the necessary headers you either have to: 1) Test as you indicated above, then fix if it fails on platform X. 2) Do a manual ordit of the code.
As an aside, I've always wanted a sort of "conceptual" std lib implementation, that included in each header nothing except what absolutely has to be there. Just the declarations would do, so we could do compile-time tests against it to verify inclusion of the right headers: the only tricky bit is getting the compile time constants correct so that it can still compile meta code. Any volunteers? :->
John: I'm not sure I understand the only tricky bit. Can you pls elaborate?
Let's suppose that we did write a minimal std lib that included in each header only those things that the header absolutely guarentees. Most of the headers would just contain declarations more or less cut and pasted from the std. There are a few areas though where we would need to define real definitions: std::numeric_limits<long double>::digits would have to have the right value for the platform the lib was used on, or else compile-time decisions based on the value would do the wrong thing. This extends to all the limits macros etc as well. I guess it's probably trivial-ish with a ./configure step, but we tend not to require that around here :-( John.