Explicit direct #include vs. Non-contractual transitive #includeOrganize includesWhat is the difference between #include <filename> and #include “filename”?What does the explicit keyword mean?How do I include a JavaScript file in another JavaScript file?Difference between require, include, require_once and include_once?In Node.js, how do I “include” functions from my other files?C++ header-only include patternInclude another HTML file in a HTML fileEncapsulting an “include” so only selected classes are exposedProvided header file does not #include <string> & not allowed to alter. How can I include it in my cpp file?Stuck on class type redefinition error despite using include guards and pragma once
How to make all magic-casting innate, but still rare?
Should I email my professor to clear up a (possibly very irrelevant) awkward misunderstanding?
Why does my system use more RAM after an hour of usage?
Basic power tool set for Home repair and simple projects
Redirecting output only on a successful command call
Leaving job close to major deadlines
XML Query Question
My student in one course asks for paid tutoring in another course. Appropriate?
What is the precise meaning of "подсел на мак"?
Explicit direct #include vs. Non-contractual transitive #include
How can Caller ID be faked?
What is the context for Napoleon's quote "[the Austrians] did not know the value of five minutes"?
Why is gun control associated with the socially liberal Democratic party?
At what temperature should the earth be cooked to prevent human infection?
How to prevent cables getting intertwined
Positive cumulative sum of difference
Why do you need to heat the pan before heating the olive oil?
100-doors puzzle
What kind of chart is this?
I have found ports on my Samsung smart tv running a display service. What can I do with it?
Is the infant mortality rate among African-American babies in Youngstown, Ohio greater than that of babies in Iran?
My husband's visa refused but mine wasn't -- can I travel?
Is it a bad idea to have a pen name with only an initial for a surname?
Can I drive in EU states and Switzerland with German proof of a surrendered U.S. license?
Explicit direct #include vs. Non-contractual transitive #include
Organize includesWhat is the difference between #include <filename> and #include “filename”?What does the explicit keyword mean?How do I include a JavaScript file in another JavaScript file?Difference between require, include, require_once and include_once?In Node.js, how do I “include” functions from my other files?C++ header-only include patternInclude another HTML file in a HTML fileEncapsulting an “include” so only selected classes are exposedProvided header file does not #include <string> & not allowed to alter. How can I include it in my cpp file?Stuck on class type redefinition error despite using include guards and pragma once
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
Say we have this header file:
MyClass.hpp
#pragma once
#include <vector>
class MyClass
public:
MyClass(double);
/* ... */
private:
std::vector<double> internal_values;
;
Now, whenever we use #include "MyClass.hpp"
in some other hpp or cpp file, we effectively also #include <vector>
, despite the fact that we do not need it. The reason I am saying it is not needed is that std::vector
is only used internally in MyClass
, but it is not required at all to actually interact with this class.
As a result, I could write
Version 1: SomeOtherHeader.hpp
#pragma once
#include "MyClass.hpp"
void func(const MyClass&, const std::vector<double>&);
whereas I probably should write
Version 2: SomeOtherHeader.hpp
#pragma once
#include "MyClass.hpp"
#include <vector>
void func(const MyClass&, const std::vector<double>&);
to prevent a dependency on the internal workings of MyClass
. Or should I?
I obviously realise that MyClass
needs <vector>
to work. So this may be more of a philosophical question. But would it not be good to be able to decide which headers get exposed when importing (i.e. limit what gets loaded into the namespace)? So that each header is required to #include
what it needs, without getting away by implicitly including something that another header needed down the chain?
c++ header include c++17
|
show 3 more comments
Say we have this header file:
MyClass.hpp
#pragma once
#include <vector>
class MyClass
public:
MyClass(double);
/* ... */
private:
std::vector<double> internal_values;
;
Now, whenever we use #include "MyClass.hpp"
in some other hpp or cpp file, we effectively also #include <vector>
, despite the fact that we do not need it. The reason I am saying it is not needed is that std::vector
is only used internally in MyClass
, but it is not required at all to actually interact with this class.
As a result, I could write
Version 1: SomeOtherHeader.hpp
#pragma once
#include "MyClass.hpp"
void func(const MyClass&, const std::vector<double>&);
whereas I probably should write
Version 2: SomeOtherHeader.hpp
#pragma once
#include "MyClass.hpp"
#include <vector>
void func(const MyClass&, const std::vector<double>&);
to prevent a dependency on the internal workings of MyClass
. Or should I?
I obviously realise that MyClass
needs <vector>
to work. So this may be more of a philosophical question. But would it not be good to be able to decide which headers get exposed when importing (i.e. limit what gets loaded into the namespace)? So that each header is required to #include
what it needs, without getting away by implicitly including something that another header needed down the chain?
c++ header include c++17
8
Yes, you should include what you need.SomeOtherHeader.hpp
should includevector
and not rely on other includes to bring that in.
– Max Langhof
13 hours ago
4
If you want to make the header free of indirect (to the code doing the#include
) dependencies (laudable, for large projects), you may want to look into the PImpl Pattern (Pointer to Implementation Pattern). Or consider using an interface class by the consumers, and a concrete class that implements that interface, which may also need a factory function. Both options have a little overhead, and a lot more code, and is overkill for small code bases.
– Eljay
13 hours ago
I've searched for a dupe but came up empty. Anyone else got something?
– Max Langhof
12 hours ago
@MaxLanghof I am afraid similar quesitons are borderline offtopic, this is the best i could find stackoverflow.com/questions/6424429/organize-includes
– formerlyknownas_463035818
12 hours ago
Extending @formerlyknownas_463035818's comment: Without separate include, your code would break as well if the developer ofMyClass
decides to replacestd::vector
with another data structure appearing more suitable – and drops the include in his own header.
– Aconcagua
12 hours ago
|
show 3 more comments
Say we have this header file:
MyClass.hpp
#pragma once
#include <vector>
class MyClass
public:
MyClass(double);
/* ... */
private:
std::vector<double> internal_values;
;
Now, whenever we use #include "MyClass.hpp"
in some other hpp or cpp file, we effectively also #include <vector>
, despite the fact that we do not need it. The reason I am saying it is not needed is that std::vector
is only used internally in MyClass
, but it is not required at all to actually interact with this class.
As a result, I could write
Version 1: SomeOtherHeader.hpp
#pragma once
#include "MyClass.hpp"
void func(const MyClass&, const std::vector<double>&);
whereas I probably should write
Version 2: SomeOtherHeader.hpp
#pragma once
#include "MyClass.hpp"
#include <vector>
void func(const MyClass&, const std::vector<double>&);
to prevent a dependency on the internal workings of MyClass
. Or should I?
I obviously realise that MyClass
needs <vector>
to work. So this may be more of a philosophical question. But would it not be good to be able to decide which headers get exposed when importing (i.e. limit what gets loaded into the namespace)? So that each header is required to #include
what it needs, without getting away by implicitly including something that another header needed down the chain?
c++ header include c++17
Say we have this header file:
MyClass.hpp
#pragma once
#include <vector>
class MyClass
public:
MyClass(double);
/* ... */
private:
std::vector<double> internal_values;
;
Now, whenever we use #include "MyClass.hpp"
in some other hpp or cpp file, we effectively also #include <vector>
, despite the fact that we do not need it. The reason I am saying it is not needed is that std::vector
is only used internally in MyClass
, but it is not required at all to actually interact with this class.
As a result, I could write
Version 1: SomeOtherHeader.hpp
#pragma once
#include "MyClass.hpp"
void func(const MyClass&, const std::vector<double>&);
whereas I probably should write
Version 2: SomeOtherHeader.hpp
#pragma once
#include "MyClass.hpp"
#include <vector>
void func(const MyClass&, const std::vector<double>&);
to prevent a dependency on the internal workings of MyClass
. Or should I?
I obviously realise that MyClass
needs <vector>
to work. So this may be more of a philosophical question. But would it not be good to be able to decide which headers get exposed when importing (i.e. limit what gets loaded into the namespace)? So that each header is required to #include
what it needs, without getting away by implicitly including something that another header needed down the chain?
c++ header include c++17
c++ header include c++17
edited 58 mins ago
Deduplicator
36.1k65291
36.1k65291
asked 13 hours ago
Phil-ZXXPhil-ZXX
303319
303319
8
Yes, you should include what you need.SomeOtherHeader.hpp
should includevector
and not rely on other includes to bring that in.
– Max Langhof
13 hours ago
4
If you want to make the header free of indirect (to the code doing the#include
) dependencies (laudable, for large projects), you may want to look into the PImpl Pattern (Pointer to Implementation Pattern). Or consider using an interface class by the consumers, and a concrete class that implements that interface, which may also need a factory function. Both options have a little overhead, and a lot more code, and is overkill for small code bases.
– Eljay
13 hours ago
I've searched for a dupe but came up empty. Anyone else got something?
– Max Langhof
12 hours ago
@MaxLanghof I am afraid similar quesitons are borderline offtopic, this is the best i could find stackoverflow.com/questions/6424429/organize-includes
– formerlyknownas_463035818
12 hours ago
Extending @formerlyknownas_463035818's comment: Without separate include, your code would break as well if the developer ofMyClass
decides to replacestd::vector
with another data structure appearing more suitable – and drops the include in his own header.
– Aconcagua
12 hours ago
|
show 3 more comments
8
Yes, you should include what you need.SomeOtherHeader.hpp
should includevector
and not rely on other includes to bring that in.
– Max Langhof
13 hours ago
4
If you want to make the header free of indirect (to the code doing the#include
) dependencies (laudable, for large projects), you may want to look into the PImpl Pattern (Pointer to Implementation Pattern). Or consider using an interface class by the consumers, and a concrete class that implements that interface, which may also need a factory function. Both options have a little overhead, and a lot more code, and is overkill for small code bases.
– Eljay
13 hours ago
I've searched for a dupe but came up empty. Anyone else got something?
– Max Langhof
12 hours ago
@MaxLanghof I am afraid similar quesitons are borderline offtopic, this is the best i could find stackoverflow.com/questions/6424429/organize-includes
– formerlyknownas_463035818
12 hours ago
Extending @formerlyknownas_463035818's comment: Without separate include, your code would break as well if the developer ofMyClass
decides to replacestd::vector
with another data structure appearing more suitable – and drops the include in his own header.
– Aconcagua
12 hours ago
8
8
Yes, you should include what you need.
SomeOtherHeader.hpp
should include vector
and not rely on other includes to bring that in.– Max Langhof
13 hours ago
Yes, you should include what you need.
SomeOtherHeader.hpp
should include vector
and not rely on other includes to bring that in.– Max Langhof
13 hours ago
4
4
If you want to make the header free of indirect (to the code doing the
#include
) dependencies (laudable, for large projects), you may want to look into the PImpl Pattern (Pointer to Implementation Pattern). Or consider using an interface class by the consumers, and a concrete class that implements that interface, which may also need a factory function. Both options have a little overhead, and a lot more code, and is overkill for small code bases.– Eljay
13 hours ago
If you want to make the header free of indirect (to the code doing the
#include
) dependencies (laudable, for large projects), you may want to look into the PImpl Pattern (Pointer to Implementation Pattern). Or consider using an interface class by the consumers, and a concrete class that implements that interface, which may also need a factory function. Both options have a little overhead, and a lot more code, and is overkill for small code bases.– Eljay
13 hours ago
I've searched for a dupe but came up empty. Anyone else got something?
– Max Langhof
12 hours ago
I've searched for a dupe but came up empty. Anyone else got something?
– Max Langhof
12 hours ago
@MaxLanghof I am afraid similar quesitons are borderline offtopic, this is the best i could find stackoverflow.com/questions/6424429/organize-includes
– formerlyknownas_463035818
12 hours ago
@MaxLanghof I am afraid similar quesitons are borderline offtopic, this is the best i could find stackoverflow.com/questions/6424429/organize-includes
– formerlyknownas_463035818
12 hours ago
Extending @formerlyknownas_463035818's comment: Without separate include, your code would break as well if the developer of
MyClass
decides to replace std::vector
with another data structure appearing more suitable – and drops the include in his own header.– Aconcagua
12 hours ago
Extending @formerlyknownas_463035818's comment: Without separate include, your code would break as well if the developer of
MyClass
decides to replace std::vector
with another data structure appearing more suitable – and drops the include in his own header.– Aconcagua
12 hours ago
|
show 3 more comments
6 Answers
6
active
oldest
votes
to prevent a dependency on the internal workings of MyClass. Or should I?
Yes, you should and for pretty much for that reason. Unless you want to specify that MyClass.hpp is guaranteed to include <vector>
, you cannot rely on one including the other. And there is no good reason to be forced to provide such guarantee. If there is no such guarantee, then you rely on an implementation detail of MyClass.hpp that may change in future, which will break your code.
I obviously realise that MyClass needs vector to work.
Does it? Couldn't it use for example boost::container::small_vector
instead?
In this example MyClass needs std::vector
But what about the needs of MyClass in future? Programs evolve, and what a class needs today is not always the same that the class needs tomorrow.
But would it not be good to be able to decide which headers get exposed when importing
Preventing transitive inclusion is not possible.
Modules introduced in C++20 are a feature that may be used instead of pp-inclusion and are intended to help solve this.
Right now, you can avoid including any implementation detail dependencies by using the PIMPL pattern ("Pointer to implementation"). But PIMPL introduces a layer of indirection and more significantly, requires dynamic allocation which has performance implications. Depending on context, these implications may be negligible or significant.
1
"Does it? Couldn't it use for example boost::container::small_vector instead?" In this example MyClass needsstd::vector
. But that's exactly my issue. Ideally#include <vector>
(or any other vector include) does not carry to the next layer, when it shouldn't.
– Phil-ZXX
12 hours ago
1
@Phil-ZXX 'In this example MyClass needs std::vector' – but that could change any time, couldn't it?
– Aconcagua
12 hours ago
1
@Aconcagua Which is why it would (in theory) be neat to hide whatever vector-include it uses, no?
– Phil-ZXX
12 hours ago
add a comment |
Consider that code is not just to be written once but it evolves over time.
Lets assume you wrote the code and now my task would be to refactor it. For some reason I want to replace MyClass
with YourClass
and lets say they have the same interface. I would simply have to replace any occurence of MyClass
with YourClass
to arrive at this:
/* Version 1: SomeOtherHeader.hpp */
#pragma once
#include "YourClass.hpp"
void func(const YourClass& a, const std::vector<double>& b);
I did everything correct, but still the code would fail to compile (because YourClass
is not including std::vector
). In this particular example I would get a clear error message and the fix would be obvious. However, things can get messy rather fast if such dependencies span across several headers, if there are many of such dependencies and if the SomeOtherHeader.hpp
contains more than just a single declaration.
There are more things that can go wrong. Eg the author of MyClass
could decided that they actually can drop the include in favor of a forward declaration. Also then SomeOtherHeader
will break. It boils down to: If you do not include vector
in SomeOtherHeader
then there is a hidden dependency, which is bad.
The rule of thumb to prevent such problems is: Include what you use.
add a comment |
You should use explicit #include
s to have a non destructive workflow. Let's say that MyClass
is used in 50 different source files. They don't include vector
. Suddenly, you have to change std::vector
in MyClass.h
for some other container. Then all the 50 source files will either need to include vector
or you will need to leave it in MyClass.h
.
This would be redundant and it could increase application size, compilation time and even run time (static variable initialization) unnecessarily.
New contributor
1
Unused headers won't increase application size (if designed correctly, at least); still they'd increase compilation time...
– Aconcagua
12 hours ago
1
@Aconcagua Some headers things do. In particular, headers that have global variables protected by a "nifty counter". Try including<iostream>
without using anything from it, and see the size increase (assuming<iostream>
wasn't used by anything else). This is not the only reason to avoid globals though, so this is kinda rare.
– eerorika
11 hours ago
@eerorika Question would be then: Good (or even correct) design?
– Aconcagua
11 hours ago
add a comment |
If your MyClass
has a member of type std::vector<double>
then the header that defines MyClass
needs to #include <vector>
. Otherwise, the only way users of MyClass
can compile is if they #include <vector>
before including the definition of MyClass
.
Although the member is private
, it is still part of the class, so the compiler needs to see a complete type definition. Otherwise, it cannot do things such as compute sizeof(MyClass)
, or instantiate any MyClass
objects.
If you want to break the dependency between your header and <vector>
there are techniques. For example, the pimpl ("pointer to implementation") idiom.
class MyClass
public:
MyClass(double first_value);
/* ... */
private:
void *pimpl;
;
and, in the source file that defines members of the class;
#include <vector>
#include "MyClass.hpp"
MyClass::MyClass(double first_value) : pimpl(new std::vector<double>())
(and also, presumably, do something with first_value
, but I have omitted that).
The tradeoff is that every member function that needs to use the vector needs to obtain it from the pimpl
. For example, if you want to get a reference to the allocated vector
void MyClass::some_member_function()
std::vector<double> &internal_data = *static_cast<std::vector<double> *>(pimpl);
The destructor of MyClass
will also need to release the dynamically allocated vector.
This also limits some options for the class definition. For example, MyClass
cannot have a member function that returns a std::vector<double>
by value (unless you #include <vector>
)
You'll need to decide if techniques like the pimpl idiom are worth the effort to make your class work. Personally, unless there is some OTHER compelling reasons to separate the class implementation from the class using the pimpl idiom, I would simply accept the need for #include <vector>
in your header file.
add a comment |
Yes, the using file should include <vector>
explicitly, as that is a dependency it needs.
However, I wouldn't fret. If someone refactors MyClass.hpp
to remove the <vector>
include, the compiler will point them at every single file that was lacking the explicit <vector>
include, relying on the implicit include. It is usually a no-brainer to fix this type of errors, and once the code compiles again, some of the missing explicit includes will have been fixed.
In the end, the compiler is much more efficient at spotting missing includes than any human being.
add a comment |
As others have said, it is safer to directly include the files you use, in terms of being protected from future changes to the file you're relying on to forward it.
It is also generally considered cleaner to have your dependencies immediately there. If you want to check what this "MyClass" object is, you want to just scroll to the top and ask your IDE to take you to the relevant header.
It's worth noting that it's safe to include the same standard header multiple times, as provided by a standard library guarantee. In practice, that means that the implementation of (in say clang's libc++) will start with an #include
guard. Modern compilers are so familiar with the include guard idiom (especially as applied by their own standard library implementations) that they can avoid even loading the files. So the only thing that you lose in exchange for that safety and clarity is having to type an extra dozen or so letters.
All that being agreed with everyone else, I have re-read it and I don't think your question was actually "Should I do this?" so much as "Why am I even allowed to not do this?" Or "Why doesn't the compiler insulate me from my includes' includes?"
There is one important exception to the "directly include what you use" rule. That is headers which, as part of their specification, include additional headers. For example <iostream
> (which is of course itself part of the standard library) is guaranteed as of c++11 to include <istream>
and <ostream>
. One might say "why not just have the contents of <istream>
and <ostream>
moved into <iostream>
directly?" but there are clarity and compilation speed advantages to having the option of splitting them up if only one is needed. (And, no doubt for c++, there are historical reasons too) You can of course do this for your own headers too. (It's more of an Objective-C thing, but they have the same include mechanics and conventionally use them for umbrella headers, whose sole job is to include other files.)
There is another fundamental reason that headers your includes include get included. That is that, in general, your headers don't make sense without them. Suppose that your MyClass.hpp
file contains the following type synonym
using NumberPack = std::vector<unsigned int>;
and the following self-descriptive function
NumberPack getFirstTenNumers();
Now suppose that another file includes MyClass.hpp
and has the following.
NumberPack counter = getFirstTenNumbers();
for (auto c : counter)
std::cout << c << "n"
What's going on here is that you may not want to write into your code that you're using <vector>
. That is an implementation detail that you don't want to have to worry about. NumberPack
could, as far as you're concerned, be implemented as some other container or an iterator or a generator type thing or something else, so long as it follows its spec. But the compiler needs to know what it actually is: it can't make effective use of parent dependencies without knowing what the grandparent dependency headers are. A side effect of that is that you get away with using them.
Or, of course, the third reason is just "Because that's not C++." Yes, one could have a language in which did not get second generation dependencies passed down, or you had to expressly request it. It's just that it would be a different language, and in particular would not fit into the old text include based style of c++ or friends.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56596929%2fexplicit-direct-include-vs-non-contractual-transitive-include%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
to prevent a dependency on the internal workings of MyClass. Or should I?
Yes, you should and for pretty much for that reason. Unless you want to specify that MyClass.hpp is guaranteed to include <vector>
, you cannot rely on one including the other. And there is no good reason to be forced to provide such guarantee. If there is no such guarantee, then you rely on an implementation detail of MyClass.hpp that may change in future, which will break your code.
I obviously realise that MyClass needs vector to work.
Does it? Couldn't it use for example boost::container::small_vector
instead?
In this example MyClass needs std::vector
But what about the needs of MyClass in future? Programs evolve, and what a class needs today is not always the same that the class needs tomorrow.
But would it not be good to be able to decide which headers get exposed when importing
Preventing transitive inclusion is not possible.
Modules introduced in C++20 are a feature that may be used instead of pp-inclusion and are intended to help solve this.
Right now, you can avoid including any implementation detail dependencies by using the PIMPL pattern ("Pointer to implementation"). But PIMPL introduces a layer of indirection and more significantly, requires dynamic allocation which has performance implications. Depending on context, these implications may be negligible or significant.
1
"Does it? Couldn't it use for example boost::container::small_vector instead?" In this example MyClass needsstd::vector
. But that's exactly my issue. Ideally#include <vector>
(or any other vector include) does not carry to the next layer, when it shouldn't.
– Phil-ZXX
12 hours ago
1
@Phil-ZXX 'In this example MyClass needs std::vector' – but that could change any time, couldn't it?
– Aconcagua
12 hours ago
1
@Aconcagua Which is why it would (in theory) be neat to hide whatever vector-include it uses, no?
– Phil-ZXX
12 hours ago
add a comment |
to prevent a dependency on the internal workings of MyClass. Or should I?
Yes, you should and for pretty much for that reason. Unless you want to specify that MyClass.hpp is guaranteed to include <vector>
, you cannot rely on one including the other. And there is no good reason to be forced to provide such guarantee. If there is no such guarantee, then you rely on an implementation detail of MyClass.hpp that may change in future, which will break your code.
I obviously realise that MyClass needs vector to work.
Does it? Couldn't it use for example boost::container::small_vector
instead?
In this example MyClass needs std::vector
But what about the needs of MyClass in future? Programs evolve, and what a class needs today is not always the same that the class needs tomorrow.
But would it not be good to be able to decide which headers get exposed when importing
Preventing transitive inclusion is not possible.
Modules introduced in C++20 are a feature that may be used instead of pp-inclusion and are intended to help solve this.
Right now, you can avoid including any implementation detail dependencies by using the PIMPL pattern ("Pointer to implementation"). But PIMPL introduces a layer of indirection and more significantly, requires dynamic allocation which has performance implications. Depending on context, these implications may be negligible or significant.
1
"Does it? Couldn't it use for example boost::container::small_vector instead?" In this example MyClass needsstd::vector
. But that's exactly my issue. Ideally#include <vector>
(or any other vector include) does not carry to the next layer, when it shouldn't.
– Phil-ZXX
12 hours ago
1
@Phil-ZXX 'In this example MyClass needs std::vector' – but that could change any time, couldn't it?
– Aconcagua
12 hours ago
1
@Aconcagua Which is why it would (in theory) be neat to hide whatever vector-include it uses, no?
– Phil-ZXX
12 hours ago
add a comment |
to prevent a dependency on the internal workings of MyClass. Or should I?
Yes, you should and for pretty much for that reason. Unless you want to specify that MyClass.hpp is guaranteed to include <vector>
, you cannot rely on one including the other. And there is no good reason to be forced to provide such guarantee. If there is no such guarantee, then you rely on an implementation detail of MyClass.hpp that may change in future, which will break your code.
I obviously realise that MyClass needs vector to work.
Does it? Couldn't it use for example boost::container::small_vector
instead?
In this example MyClass needs std::vector
But what about the needs of MyClass in future? Programs evolve, and what a class needs today is not always the same that the class needs tomorrow.
But would it not be good to be able to decide which headers get exposed when importing
Preventing transitive inclusion is not possible.
Modules introduced in C++20 are a feature that may be used instead of pp-inclusion and are intended to help solve this.
Right now, you can avoid including any implementation detail dependencies by using the PIMPL pattern ("Pointer to implementation"). But PIMPL introduces a layer of indirection and more significantly, requires dynamic allocation which has performance implications. Depending on context, these implications may be negligible or significant.
to prevent a dependency on the internal workings of MyClass. Or should I?
Yes, you should and for pretty much for that reason. Unless you want to specify that MyClass.hpp is guaranteed to include <vector>
, you cannot rely on one including the other. And there is no good reason to be forced to provide such guarantee. If there is no such guarantee, then you rely on an implementation detail of MyClass.hpp that may change in future, which will break your code.
I obviously realise that MyClass needs vector to work.
Does it? Couldn't it use for example boost::container::small_vector
instead?
In this example MyClass needs std::vector
But what about the needs of MyClass in future? Programs evolve, and what a class needs today is not always the same that the class needs tomorrow.
But would it not be good to be able to decide which headers get exposed when importing
Preventing transitive inclusion is not possible.
Modules introduced in C++20 are a feature that may be used instead of pp-inclusion and are intended to help solve this.
Right now, you can avoid including any implementation detail dependencies by using the PIMPL pattern ("Pointer to implementation"). But PIMPL introduces a layer of indirection and more significantly, requires dynamic allocation which has performance implications. Depending on context, these implications may be negligible or significant.
edited 12 hours ago
answered 12 hours ago
eerorikaeerorika
95.1k672140
95.1k672140
1
"Does it? Couldn't it use for example boost::container::small_vector instead?" In this example MyClass needsstd::vector
. But that's exactly my issue. Ideally#include <vector>
(or any other vector include) does not carry to the next layer, when it shouldn't.
– Phil-ZXX
12 hours ago
1
@Phil-ZXX 'In this example MyClass needs std::vector' – but that could change any time, couldn't it?
– Aconcagua
12 hours ago
1
@Aconcagua Which is why it would (in theory) be neat to hide whatever vector-include it uses, no?
– Phil-ZXX
12 hours ago
add a comment |
1
"Does it? Couldn't it use for example boost::container::small_vector instead?" In this example MyClass needsstd::vector
. But that's exactly my issue. Ideally#include <vector>
(or any other vector include) does not carry to the next layer, when it shouldn't.
– Phil-ZXX
12 hours ago
1
@Phil-ZXX 'In this example MyClass needs std::vector' – but that could change any time, couldn't it?
– Aconcagua
12 hours ago
1
@Aconcagua Which is why it would (in theory) be neat to hide whatever vector-include it uses, no?
– Phil-ZXX
12 hours ago
1
1
"Does it? Couldn't it use for example boost::container::small_vector instead?" In this example MyClass needs
std::vector
. But that's exactly my issue. Ideally #include <vector>
(or any other vector include) does not carry to the next layer, when it shouldn't.– Phil-ZXX
12 hours ago
"Does it? Couldn't it use for example boost::container::small_vector instead?" In this example MyClass needs
std::vector
. But that's exactly my issue. Ideally #include <vector>
(or any other vector include) does not carry to the next layer, when it shouldn't.– Phil-ZXX
12 hours ago
1
1
@Phil-ZXX 'In this example MyClass needs std::vector' – but that could change any time, couldn't it?
– Aconcagua
12 hours ago
@Phil-ZXX 'In this example MyClass needs std::vector' – but that could change any time, couldn't it?
– Aconcagua
12 hours ago
1
1
@Aconcagua Which is why it would (in theory) be neat to hide whatever vector-include it uses, no?
– Phil-ZXX
12 hours ago
@Aconcagua Which is why it would (in theory) be neat to hide whatever vector-include it uses, no?
– Phil-ZXX
12 hours ago
add a comment |
Consider that code is not just to be written once but it evolves over time.
Lets assume you wrote the code and now my task would be to refactor it. For some reason I want to replace MyClass
with YourClass
and lets say they have the same interface. I would simply have to replace any occurence of MyClass
with YourClass
to arrive at this:
/* Version 1: SomeOtherHeader.hpp */
#pragma once
#include "YourClass.hpp"
void func(const YourClass& a, const std::vector<double>& b);
I did everything correct, but still the code would fail to compile (because YourClass
is not including std::vector
). In this particular example I would get a clear error message and the fix would be obvious. However, things can get messy rather fast if such dependencies span across several headers, if there are many of such dependencies and if the SomeOtherHeader.hpp
contains more than just a single declaration.
There are more things that can go wrong. Eg the author of MyClass
could decided that they actually can drop the include in favor of a forward declaration. Also then SomeOtherHeader
will break. It boils down to: If you do not include vector
in SomeOtherHeader
then there is a hidden dependency, which is bad.
The rule of thumb to prevent such problems is: Include what you use.
add a comment |
Consider that code is not just to be written once but it evolves over time.
Lets assume you wrote the code and now my task would be to refactor it. For some reason I want to replace MyClass
with YourClass
and lets say they have the same interface. I would simply have to replace any occurence of MyClass
with YourClass
to arrive at this:
/* Version 1: SomeOtherHeader.hpp */
#pragma once
#include "YourClass.hpp"
void func(const YourClass& a, const std::vector<double>& b);
I did everything correct, but still the code would fail to compile (because YourClass
is not including std::vector
). In this particular example I would get a clear error message and the fix would be obvious. However, things can get messy rather fast if such dependencies span across several headers, if there are many of such dependencies and if the SomeOtherHeader.hpp
contains more than just a single declaration.
There are more things that can go wrong. Eg the author of MyClass
could decided that they actually can drop the include in favor of a forward declaration. Also then SomeOtherHeader
will break. It boils down to: If you do not include vector
in SomeOtherHeader
then there is a hidden dependency, which is bad.
The rule of thumb to prevent such problems is: Include what you use.
add a comment |
Consider that code is not just to be written once but it evolves over time.
Lets assume you wrote the code and now my task would be to refactor it. For some reason I want to replace MyClass
with YourClass
and lets say they have the same interface. I would simply have to replace any occurence of MyClass
with YourClass
to arrive at this:
/* Version 1: SomeOtherHeader.hpp */
#pragma once
#include "YourClass.hpp"
void func(const YourClass& a, const std::vector<double>& b);
I did everything correct, but still the code would fail to compile (because YourClass
is not including std::vector
). In this particular example I would get a clear error message and the fix would be obvious. However, things can get messy rather fast if such dependencies span across several headers, if there are many of such dependencies and if the SomeOtherHeader.hpp
contains more than just a single declaration.
There are more things that can go wrong. Eg the author of MyClass
could decided that they actually can drop the include in favor of a forward declaration. Also then SomeOtherHeader
will break. It boils down to: If you do not include vector
in SomeOtherHeader
then there is a hidden dependency, which is bad.
The rule of thumb to prevent such problems is: Include what you use.
Consider that code is not just to be written once but it evolves over time.
Lets assume you wrote the code and now my task would be to refactor it. For some reason I want to replace MyClass
with YourClass
and lets say they have the same interface. I would simply have to replace any occurence of MyClass
with YourClass
to arrive at this:
/* Version 1: SomeOtherHeader.hpp */
#pragma once
#include "YourClass.hpp"
void func(const YourClass& a, const std::vector<double>& b);
I did everything correct, but still the code would fail to compile (because YourClass
is not including std::vector
). In this particular example I would get a clear error message and the fix would be obvious. However, things can get messy rather fast if such dependencies span across several headers, if there are many of such dependencies and if the SomeOtherHeader.hpp
contains more than just a single declaration.
There are more things that can go wrong. Eg the author of MyClass
could decided that they actually can drop the include in favor of a forward declaration. Also then SomeOtherHeader
will break. It boils down to: If you do not include vector
in SomeOtherHeader
then there is a hidden dependency, which is bad.
The rule of thumb to prevent such problems is: Include what you use.
answered 12 hours ago
formerlyknownas_463035818formerlyknownas_463035818
22.1k43277
22.1k43277
add a comment |
add a comment |
You should use explicit #include
s to have a non destructive workflow. Let's say that MyClass
is used in 50 different source files. They don't include vector
. Suddenly, you have to change std::vector
in MyClass.h
for some other container. Then all the 50 source files will either need to include vector
or you will need to leave it in MyClass.h
.
This would be redundant and it could increase application size, compilation time and even run time (static variable initialization) unnecessarily.
New contributor
1
Unused headers won't increase application size (if designed correctly, at least); still they'd increase compilation time...
– Aconcagua
12 hours ago
1
@Aconcagua Some headers things do. In particular, headers that have global variables protected by a "nifty counter". Try including<iostream>
without using anything from it, and see the size increase (assuming<iostream>
wasn't used by anything else). This is not the only reason to avoid globals though, so this is kinda rare.
– eerorika
11 hours ago
@eerorika Question would be then: Good (or even correct) design?
– Aconcagua
11 hours ago
add a comment |
You should use explicit #include
s to have a non destructive workflow. Let's say that MyClass
is used in 50 different source files. They don't include vector
. Suddenly, you have to change std::vector
in MyClass.h
for some other container. Then all the 50 source files will either need to include vector
or you will need to leave it in MyClass.h
.
This would be redundant and it could increase application size, compilation time and even run time (static variable initialization) unnecessarily.
New contributor
1
Unused headers won't increase application size (if designed correctly, at least); still they'd increase compilation time...
– Aconcagua
12 hours ago
1
@Aconcagua Some headers things do. In particular, headers that have global variables protected by a "nifty counter". Try including<iostream>
without using anything from it, and see the size increase (assuming<iostream>
wasn't used by anything else). This is not the only reason to avoid globals though, so this is kinda rare.
– eerorika
11 hours ago
@eerorika Question would be then: Good (or even correct) design?
– Aconcagua
11 hours ago
add a comment |
You should use explicit #include
s to have a non destructive workflow. Let's say that MyClass
is used in 50 different source files. They don't include vector
. Suddenly, you have to change std::vector
in MyClass.h
for some other container. Then all the 50 source files will either need to include vector
or you will need to leave it in MyClass.h
.
This would be redundant and it could increase application size, compilation time and even run time (static variable initialization) unnecessarily.
New contributor
You should use explicit #include
s to have a non destructive workflow. Let's say that MyClass
is used in 50 different source files. They don't include vector
. Suddenly, you have to change std::vector
in MyClass.h
for some other container. Then all the 50 source files will either need to include vector
or you will need to leave it in MyClass.h
.
This would be redundant and it could increase application size, compilation time and even run time (static variable initialization) unnecessarily.
New contributor
edited 12 hours ago
New contributor
answered 12 hours ago
Yan B.Yan B.
848
848
New contributor
New contributor
1
Unused headers won't increase application size (if designed correctly, at least); still they'd increase compilation time...
– Aconcagua
12 hours ago
1
@Aconcagua Some headers things do. In particular, headers that have global variables protected by a "nifty counter". Try including<iostream>
without using anything from it, and see the size increase (assuming<iostream>
wasn't used by anything else). This is not the only reason to avoid globals though, so this is kinda rare.
– eerorika
11 hours ago
@eerorika Question would be then: Good (or even correct) design?
– Aconcagua
11 hours ago
add a comment |
1
Unused headers won't increase application size (if designed correctly, at least); still they'd increase compilation time...
– Aconcagua
12 hours ago
1
@Aconcagua Some headers things do. In particular, headers that have global variables protected by a "nifty counter". Try including<iostream>
without using anything from it, and see the size increase (assuming<iostream>
wasn't used by anything else). This is not the only reason to avoid globals though, so this is kinda rare.
– eerorika
11 hours ago
@eerorika Question would be then: Good (or even correct) design?
– Aconcagua
11 hours ago
1
1
Unused headers won't increase application size (if designed correctly, at least); still they'd increase compilation time...
– Aconcagua
12 hours ago
Unused headers won't increase application size (if designed correctly, at least); still they'd increase compilation time...
– Aconcagua
12 hours ago
1
1
@Aconcagua Some headers things do. In particular, headers that have global variables protected by a "nifty counter". Try including
<iostream>
without using anything from it, and see the size increase (assuming <iostream>
wasn't used by anything else). This is not the only reason to avoid globals though, so this is kinda rare.– eerorika
11 hours ago
@Aconcagua Some headers things do. In particular, headers that have global variables protected by a "nifty counter". Try including
<iostream>
without using anything from it, and see the size increase (assuming <iostream>
wasn't used by anything else). This is not the only reason to avoid globals though, so this is kinda rare.– eerorika
11 hours ago
@eerorika Question would be then: Good (or even correct) design?
– Aconcagua
11 hours ago
@eerorika Question would be then: Good (or even correct) design?
– Aconcagua
11 hours ago
add a comment |
If your MyClass
has a member of type std::vector<double>
then the header that defines MyClass
needs to #include <vector>
. Otherwise, the only way users of MyClass
can compile is if they #include <vector>
before including the definition of MyClass
.
Although the member is private
, it is still part of the class, so the compiler needs to see a complete type definition. Otherwise, it cannot do things such as compute sizeof(MyClass)
, or instantiate any MyClass
objects.
If you want to break the dependency between your header and <vector>
there are techniques. For example, the pimpl ("pointer to implementation") idiom.
class MyClass
public:
MyClass(double first_value);
/* ... */
private:
void *pimpl;
;
and, in the source file that defines members of the class;
#include <vector>
#include "MyClass.hpp"
MyClass::MyClass(double first_value) : pimpl(new std::vector<double>())
(and also, presumably, do something with first_value
, but I have omitted that).
The tradeoff is that every member function that needs to use the vector needs to obtain it from the pimpl
. For example, if you want to get a reference to the allocated vector
void MyClass::some_member_function()
std::vector<double> &internal_data = *static_cast<std::vector<double> *>(pimpl);
The destructor of MyClass
will also need to release the dynamically allocated vector.
This also limits some options for the class definition. For example, MyClass
cannot have a member function that returns a std::vector<double>
by value (unless you #include <vector>
)
You'll need to decide if techniques like the pimpl idiom are worth the effort to make your class work. Personally, unless there is some OTHER compelling reasons to separate the class implementation from the class using the pimpl idiom, I would simply accept the need for #include <vector>
in your header file.
add a comment |
If your MyClass
has a member of type std::vector<double>
then the header that defines MyClass
needs to #include <vector>
. Otherwise, the only way users of MyClass
can compile is if they #include <vector>
before including the definition of MyClass
.
Although the member is private
, it is still part of the class, so the compiler needs to see a complete type definition. Otherwise, it cannot do things such as compute sizeof(MyClass)
, or instantiate any MyClass
objects.
If you want to break the dependency between your header and <vector>
there are techniques. For example, the pimpl ("pointer to implementation") idiom.
class MyClass
public:
MyClass(double first_value);
/* ... */
private:
void *pimpl;
;
and, in the source file that defines members of the class;
#include <vector>
#include "MyClass.hpp"
MyClass::MyClass(double first_value) : pimpl(new std::vector<double>())
(and also, presumably, do something with first_value
, but I have omitted that).
The tradeoff is that every member function that needs to use the vector needs to obtain it from the pimpl
. For example, if you want to get a reference to the allocated vector
void MyClass::some_member_function()
std::vector<double> &internal_data = *static_cast<std::vector<double> *>(pimpl);
The destructor of MyClass
will also need to release the dynamically allocated vector.
This also limits some options for the class definition. For example, MyClass
cannot have a member function that returns a std::vector<double>
by value (unless you #include <vector>
)
You'll need to decide if techniques like the pimpl idiom are worth the effort to make your class work. Personally, unless there is some OTHER compelling reasons to separate the class implementation from the class using the pimpl idiom, I would simply accept the need for #include <vector>
in your header file.
add a comment |
If your MyClass
has a member of type std::vector<double>
then the header that defines MyClass
needs to #include <vector>
. Otherwise, the only way users of MyClass
can compile is if they #include <vector>
before including the definition of MyClass
.
Although the member is private
, it is still part of the class, so the compiler needs to see a complete type definition. Otherwise, it cannot do things such as compute sizeof(MyClass)
, or instantiate any MyClass
objects.
If you want to break the dependency between your header and <vector>
there are techniques. For example, the pimpl ("pointer to implementation") idiom.
class MyClass
public:
MyClass(double first_value);
/* ... */
private:
void *pimpl;
;
and, in the source file that defines members of the class;
#include <vector>
#include "MyClass.hpp"
MyClass::MyClass(double first_value) : pimpl(new std::vector<double>())
(and also, presumably, do something with first_value
, but I have omitted that).
The tradeoff is that every member function that needs to use the vector needs to obtain it from the pimpl
. For example, if you want to get a reference to the allocated vector
void MyClass::some_member_function()
std::vector<double> &internal_data = *static_cast<std::vector<double> *>(pimpl);
The destructor of MyClass
will also need to release the dynamically allocated vector.
This also limits some options for the class definition. For example, MyClass
cannot have a member function that returns a std::vector<double>
by value (unless you #include <vector>
)
You'll need to decide if techniques like the pimpl idiom are worth the effort to make your class work. Personally, unless there is some OTHER compelling reasons to separate the class implementation from the class using the pimpl idiom, I would simply accept the need for #include <vector>
in your header file.
If your MyClass
has a member of type std::vector<double>
then the header that defines MyClass
needs to #include <vector>
. Otherwise, the only way users of MyClass
can compile is if they #include <vector>
before including the definition of MyClass
.
Although the member is private
, it is still part of the class, so the compiler needs to see a complete type definition. Otherwise, it cannot do things such as compute sizeof(MyClass)
, or instantiate any MyClass
objects.
If you want to break the dependency between your header and <vector>
there are techniques. For example, the pimpl ("pointer to implementation") idiom.
class MyClass
public:
MyClass(double first_value);
/* ... */
private:
void *pimpl;
;
and, in the source file that defines members of the class;
#include <vector>
#include "MyClass.hpp"
MyClass::MyClass(double first_value) : pimpl(new std::vector<double>())
(and also, presumably, do something with first_value
, but I have omitted that).
The tradeoff is that every member function that needs to use the vector needs to obtain it from the pimpl
. For example, if you want to get a reference to the allocated vector
void MyClass::some_member_function()
std::vector<double> &internal_data = *static_cast<std::vector<double> *>(pimpl);
The destructor of MyClass
will also need to release the dynamically allocated vector.
This also limits some options for the class definition. For example, MyClass
cannot have a member function that returns a std::vector<double>
by value (unless you #include <vector>
)
You'll need to decide if techniques like the pimpl idiom are worth the effort to make your class work. Personally, unless there is some OTHER compelling reasons to separate the class implementation from the class using the pimpl idiom, I would simply accept the need for #include <vector>
in your header file.
answered 11 hours ago
PeterPeter
28.5k32257
28.5k32257
add a comment |
add a comment |
Yes, the using file should include <vector>
explicitly, as that is a dependency it needs.
However, I wouldn't fret. If someone refactors MyClass.hpp
to remove the <vector>
include, the compiler will point them at every single file that was lacking the explicit <vector>
include, relying on the implicit include. It is usually a no-brainer to fix this type of errors, and once the code compiles again, some of the missing explicit includes will have been fixed.
In the end, the compiler is much more efficient at spotting missing includes than any human being.
add a comment |
Yes, the using file should include <vector>
explicitly, as that is a dependency it needs.
However, I wouldn't fret. If someone refactors MyClass.hpp
to remove the <vector>
include, the compiler will point them at every single file that was lacking the explicit <vector>
include, relying on the implicit include. It is usually a no-brainer to fix this type of errors, and once the code compiles again, some of the missing explicit includes will have been fixed.
In the end, the compiler is much more efficient at spotting missing includes than any human being.
add a comment |
Yes, the using file should include <vector>
explicitly, as that is a dependency it needs.
However, I wouldn't fret. If someone refactors MyClass.hpp
to remove the <vector>
include, the compiler will point them at every single file that was lacking the explicit <vector>
include, relying on the implicit include. It is usually a no-brainer to fix this type of errors, and once the code compiles again, some of the missing explicit includes will have been fixed.
In the end, the compiler is much more efficient at spotting missing includes than any human being.
Yes, the using file should include <vector>
explicitly, as that is a dependency it needs.
However, I wouldn't fret. If someone refactors MyClass.hpp
to remove the <vector>
include, the compiler will point them at every single file that was lacking the explicit <vector>
include, relying on the implicit include. It is usually a no-brainer to fix this type of errors, and once the code compiles again, some of the missing explicit includes will have been fixed.
In the end, the compiler is much more efficient at spotting missing includes than any human being.
answered 3 hours ago
cmastercmaster
26.8k64185
26.8k64185
add a comment |
add a comment |
As others have said, it is safer to directly include the files you use, in terms of being protected from future changes to the file you're relying on to forward it.
It is also generally considered cleaner to have your dependencies immediately there. If you want to check what this "MyClass" object is, you want to just scroll to the top and ask your IDE to take you to the relevant header.
It's worth noting that it's safe to include the same standard header multiple times, as provided by a standard library guarantee. In practice, that means that the implementation of (in say clang's libc++) will start with an #include
guard. Modern compilers are so familiar with the include guard idiom (especially as applied by their own standard library implementations) that they can avoid even loading the files. So the only thing that you lose in exchange for that safety and clarity is having to type an extra dozen or so letters.
All that being agreed with everyone else, I have re-read it and I don't think your question was actually "Should I do this?" so much as "Why am I even allowed to not do this?" Or "Why doesn't the compiler insulate me from my includes' includes?"
There is one important exception to the "directly include what you use" rule. That is headers which, as part of their specification, include additional headers. For example <iostream
> (which is of course itself part of the standard library) is guaranteed as of c++11 to include <istream>
and <ostream>
. One might say "why not just have the contents of <istream>
and <ostream>
moved into <iostream>
directly?" but there are clarity and compilation speed advantages to having the option of splitting them up if only one is needed. (And, no doubt for c++, there are historical reasons too) You can of course do this for your own headers too. (It's more of an Objective-C thing, but they have the same include mechanics and conventionally use them for umbrella headers, whose sole job is to include other files.)
There is another fundamental reason that headers your includes include get included. That is that, in general, your headers don't make sense without them. Suppose that your MyClass.hpp
file contains the following type synonym
using NumberPack = std::vector<unsigned int>;
and the following self-descriptive function
NumberPack getFirstTenNumers();
Now suppose that another file includes MyClass.hpp
and has the following.
NumberPack counter = getFirstTenNumbers();
for (auto c : counter)
std::cout << c << "n"
What's going on here is that you may not want to write into your code that you're using <vector>
. That is an implementation detail that you don't want to have to worry about. NumberPack
could, as far as you're concerned, be implemented as some other container or an iterator or a generator type thing or something else, so long as it follows its spec. But the compiler needs to know what it actually is: it can't make effective use of parent dependencies without knowing what the grandparent dependency headers are. A side effect of that is that you get away with using them.
Or, of course, the third reason is just "Because that's not C++." Yes, one could have a language in which did not get second generation dependencies passed down, or you had to expressly request it. It's just that it would be a different language, and in particular would not fit into the old text include based style of c++ or friends.
add a comment |
As others have said, it is safer to directly include the files you use, in terms of being protected from future changes to the file you're relying on to forward it.
It is also generally considered cleaner to have your dependencies immediately there. If you want to check what this "MyClass" object is, you want to just scroll to the top and ask your IDE to take you to the relevant header.
It's worth noting that it's safe to include the same standard header multiple times, as provided by a standard library guarantee. In practice, that means that the implementation of (in say clang's libc++) will start with an #include
guard. Modern compilers are so familiar with the include guard idiom (especially as applied by their own standard library implementations) that they can avoid even loading the files. So the only thing that you lose in exchange for that safety and clarity is having to type an extra dozen or so letters.
All that being agreed with everyone else, I have re-read it and I don't think your question was actually "Should I do this?" so much as "Why am I even allowed to not do this?" Or "Why doesn't the compiler insulate me from my includes' includes?"
There is one important exception to the "directly include what you use" rule. That is headers which, as part of their specification, include additional headers. For example <iostream
> (which is of course itself part of the standard library) is guaranteed as of c++11 to include <istream>
and <ostream>
. One might say "why not just have the contents of <istream>
and <ostream>
moved into <iostream>
directly?" but there are clarity and compilation speed advantages to having the option of splitting them up if only one is needed. (And, no doubt for c++, there are historical reasons too) You can of course do this for your own headers too. (It's more of an Objective-C thing, but they have the same include mechanics and conventionally use them for umbrella headers, whose sole job is to include other files.)
There is another fundamental reason that headers your includes include get included. That is that, in general, your headers don't make sense without them. Suppose that your MyClass.hpp
file contains the following type synonym
using NumberPack = std::vector<unsigned int>;
and the following self-descriptive function
NumberPack getFirstTenNumers();
Now suppose that another file includes MyClass.hpp
and has the following.
NumberPack counter = getFirstTenNumbers();
for (auto c : counter)
std::cout << c << "n"
What's going on here is that you may not want to write into your code that you're using <vector>
. That is an implementation detail that you don't want to have to worry about. NumberPack
could, as far as you're concerned, be implemented as some other container or an iterator or a generator type thing or something else, so long as it follows its spec. But the compiler needs to know what it actually is: it can't make effective use of parent dependencies without knowing what the grandparent dependency headers are. A side effect of that is that you get away with using them.
Or, of course, the third reason is just "Because that's not C++." Yes, one could have a language in which did not get second generation dependencies passed down, or you had to expressly request it. It's just that it would be a different language, and in particular would not fit into the old text include based style of c++ or friends.
add a comment |
As others have said, it is safer to directly include the files you use, in terms of being protected from future changes to the file you're relying on to forward it.
It is also generally considered cleaner to have your dependencies immediately there. If you want to check what this "MyClass" object is, you want to just scroll to the top and ask your IDE to take you to the relevant header.
It's worth noting that it's safe to include the same standard header multiple times, as provided by a standard library guarantee. In practice, that means that the implementation of (in say clang's libc++) will start with an #include
guard. Modern compilers are so familiar with the include guard idiom (especially as applied by their own standard library implementations) that they can avoid even loading the files. So the only thing that you lose in exchange for that safety and clarity is having to type an extra dozen or so letters.
All that being agreed with everyone else, I have re-read it and I don't think your question was actually "Should I do this?" so much as "Why am I even allowed to not do this?" Or "Why doesn't the compiler insulate me from my includes' includes?"
There is one important exception to the "directly include what you use" rule. That is headers which, as part of their specification, include additional headers. For example <iostream
> (which is of course itself part of the standard library) is guaranteed as of c++11 to include <istream>
and <ostream>
. One might say "why not just have the contents of <istream>
and <ostream>
moved into <iostream>
directly?" but there are clarity and compilation speed advantages to having the option of splitting them up if only one is needed. (And, no doubt for c++, there are historical reasons too) You can of course do this for your own headers too. (It's more of an Objective-C thing, but they have the same include mechanics and conventionally use them for umbrella headers, whose sole job is to include other files.)
There is another fundamental reason that headers your includes include get included. That is that, in general, your headers don't make sense without them. Suppose that your MyClass.hpp
file contains the following type synonym
using NumberPack = std::vector<unsigned int>;
and the following self-descriptive function
NumberPack getFirstTenNumers();
Now suppose that another file includes MyClass.hpp
and has the following.
NumberPack counter = getFirstTenNumbers();
for (auto c : counter)
std::cout << c << "n"
What's going on here is that you may not want to write into your code that you're using <vector>
. That is an implementation detail that you don't want to have to worry about. NumberPack
could, as far as you're concerned, be implemented as some other container or an iterator or a generator type thing or something else, so long as it follows its spec. But the compiler needs to know what it actually is: it can't make effective use of parent dependencies without knowing what the grandparent dependency headers are. A side effect of that is that you get away with using them.
Or, of course, the third reason is just "Because that's not C++." Yes, one could have a language in which did not get second generation dependencies passed down, or you had to expressly request it. It's just that it would be a different language, and in particular would not fit into the old text include based style of c++ or friends.
As others have said, it is safer to directly include the files you use, in terms of being protected from future changes to the file you're relying on to forward it.
It is also generally considered cleaner to have your dependencies immediately there. If you want to check what this "MyClass" object is, you want to just scroll to the top and ask your IDE to take you to the relevant header.
It's worth noting that it's safe to include the same standard header multiple times, as provided by a standard library guarantee. In practice, that means that the implementation of (in say clang's libc++) will start with an #include
guard. Modern compilers are so familiar with the include guard idiom (especially as applied by their own standard library implementations) that they can avoid even loading the files. So the only thing that you lose in exchange for that safety and clarity is having to type an extra dozen or so letters.
All that being agreed with everyone else, I have re-read it and I don't think your question was actually "Should I do this?" so much as "Why am I even allowed to not do this?" Or "Why doesn't the compiler insulate me from my includes' includes?"
There is one important exception to the "directly include what you use" rule. That is headers which, as part of their specification, include additional headers. For example <iostream
> (which is of course itself part of the standard library) is guaranteed as of c++11 to include <istream>
and <ostream>
. One might say "why not just have the contents of <istream>
and <ostream>
moved into <iostream>
directly?" but there are clarity and compilation speed advantages to having the option of splitting them up if only one is needed. (And, no doubt for c++, there are historical reasons too) You can of course do this for your own headers too. (It's more of an Objective-C thing, but they have the same include mechanics and conventionally use them for umbrella headers, whose sole job is to include other files.)
There is another fundamental reason that headers your includes include get included. That is that, in general, your headers don't make sense without them. Suppose that your MyClass.hpp
file contains the following type synonym
using NumberPack = std::vector<unsigned int>;
and the following self-descriptive function
NumberPack getFirstTenNumers();
Now suppose that another file includes MyClass.hpp
and has the following.
NumberPack counter = getFirstTenNumbers();
for (auto c : counter)
std::cout << c << "n"
What's going on here is that you may not want to write into your code that you're using <vector>
. That is an implementation detail that you don't want to have to worry about. NumberPack
could, as far as you're concerned, be implemented as some other container or an iterator or a generator type thing or something else, so long as it follows its spec. But the compiler needs to know what it actually is: it can't make effective use of parent dependencies without knowing what the grandparent dependency headers are. A side effect of that is that you get away with using them.
Or, of course, the third reason is just "Because that's not C++." Yes, one could have a language in which did not get second generation dependencies passed down, or you had to expressly request it. It's just that it would be a different language, and in particular would not fit into the old text include based style of c++ or friends.
answered 1 hour ago
JosiahJosiah
279210
279210
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56596929%2fexplicit-direct-include-vs-non-contractual-transitive-include%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
8
Yes, you should include what you need.
SomeOtherHeader.hpp
should includevector
and not rely on other includes to bring that in.– Max Langhof
13 hours ago
4
If you want to make the header free of indirect (to the code doing the
#include
) dependencies (laudable, for large projects), you may want to look into the PImpl Pattern (Pointer to Implementation Pattern). Or consider using an interface class by the consumers, and a concrete class that implements that interface, which may also need a factory function. Both options have a little overhead, and a lot more code, and is overkill for small code bases.– Eljay
13 hours ago
I've searched for a dupe but came up empty. Anyone else got something?
– Max Langhof
12 hours ago
@MaxLanghof I am afraid similar quesitons are borderline offtopic, this is the best i could find stackoverflow.com/questions/6424429/organize-includes
– formerlyknownas_463035818
12 hours ago
Extending @formerlyknownas_463035818's comment: Without separate include, your code would break as well if the developer of
MyClass
decides to replacestd::vector
with another data structure appearing more suitable – and drops the include in his own header.– Aconcagua
12 hours ago