From 50576c01442c422079856c30d9914b2c5fe4a04f Mon Sep 17 00:00:00 2001 From: Bjarne Stroustrup Date: Wed, 17 May 2017 15:06:48 -0400 Subject: [PATCH] issue #841 SF.10: Avoid dependencies on implicitly `#included` names --- CppCoreGuidelines.md | 71 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/CppCoreGuidelines.md b/CppCoreGuidelines.md index 28ee6da..47c03b0 100644 --- a/CppCoreGuidelines.md +++ b/CppCoreGuidelines.md @@ -17077,6 +17077,7 @@ Source file rule summary: * [SF.7: Don't write `using namespace` in a header file](#Rs-using-directive) * [SF.8: Use `#include` guards for all `.h` files](#Rs-guards) * [SF.9: Avoid cyclic dependencies among source files](#Rs-cycles) +* [SF.10: Avoid dependencies on implicitly `#included` names](#Rs-implicit) * [SF.20: Use `namespace`s to express logical structure](#Rs-namespace) * [SF.21: Don't use an unnamed (anonymous) namespace in a header](#Rs-unnamed) @@ -17411,6 +17412,76 @@ Eliminate cycles; don't just break them with `#include` guards. Flag all cycles. + +### SF.10: Avoid dependencies on implicitly `#included` names + +##### Reason + +Avoid surprises. +Avoid having to change `#include`s if an `#include`d header changes. +Avoid accidentally becoming dependent on implementation details and logically separate entities included in a header. + +##### Example + + #include + using namespace std; + + void use() // bad + { + string s; + cin >> s; // fine + getline(cin,s); // error: getline() not defined + if (s=="surprise") { // error == not defined + // ... + } + } + + exposes the definition of `std::string` ("why?" makes for a fun trivia question), +but it is not required to do so by transitively including the entire `` header, +resulting in the popular beginner question "why doesn't `getline(cin,s);` work?" +or even an occasional "`string`s cannot be compared with `==`). + +The solution is to explicitly `#include`: + + #include + #include + using namespace std; + + void use() + { + string s; + cin >> s; // fine + getline(cin,s); // fine + if (s=="surprise") { // fine + // ... + } + } + +##### Note + +Some headers exist exactly to collect a set of consistent declarations from a variety of headers. +For example: + + // basic_std_lib.h: + + #include + #include + #include + #include + #include + #include + +a user can now get that set of declarations with a single `#include`" + + #include "basic_std_lib.h" + +This rule against implicit inclusion is not meant to prevent such deliberate aggregation. + +##### Enforcement + +Enforcement would require some knowledge about what in a header is meant to be "exported" to users and what is there to enable implementation. +No really good solution is possible until we have modules. + ### SF.20: Use `namespace`s to express logical structure ##### Reason