开发者

Abolish include-files in C++

Suppose i have the following code (literally) in a C++ source file:

// #include <iostream> // superfluous, commented-out
using std::cout;
using std::endl;

int main()
{
    cout << "Hello World" << endl;
    return 0;
}

I can compile this code even though #include <iostream> is commented-out:

g++ -include my_cpp_std_lib_hack source.cpp

Where my_cpp_std_lib_hack is a file in some central location that includes all the files of the C++ Stan开发者_如何学Cdard Library:

#include <ciso646>
#include <climits>
#include <clocale>
...
#include <valarray>
#include <vector>

Of course, i can use proper compilation options for all compilers i care about (that being MS Visual Studio and maybe a few others), and i also use precompiled headers.

Using such a hack gives me the following advantages:

  • Fast compilation (because all of the Standard Library is precompiled)
  • No need to add #includes when all i want is adding some debugging output
  • No need to remember or look up all the time where the heck std::max is declared
  • A feeling that the STL is magically built-in to the language

So i wonder: am i doing something very wrong here?

Will this hack break down when writing large projects?

Maybe everyone else already uses this, and no one told me?


So i wonder: am i doing something very wrong here?

Yes. Sure, your headers are precompiled, but the compiler still has to do things like name lookups on the entire included mass of stuff which slows down compilation.

Will this hack break down when writing large projects?

Yes, that's pretty much the problem. Plus, if anyone else looks at that code, they're going to be wondering where std::cout (well, assume that's a user defined type) came from. Without the #includes they're going to have no idea whatsoever.

Not to mention, now you have to link against a ton of standard library features that you may have (probably could have) avoided linking against in the first place.

If you want to use precompilation that's fine, but someone should be able to build each and every implementation file even when precompilation is disabled.


The only thing "wrong" is that you are relying upon a compiler-specific command-line flag to make the files compilable. You'd need to do something different if not using GCC. Most compilers probably do provide an equivalent feature, but it is best to write portable source code rather than to unnecessarily rely on features of your specific build environment.

Other programmers shouldn't have to puzzle over your Makefiles (or Ant files, or Eclipse workspaces, or whatever) to figure out how things are working.

This may also cause problems for users of IDE's. If the IDE doesn't know what files are being included, it may not be able to provide automatic completion, source browsing, refactoring, and other such features.

(FWIW, I do think it is a good idea to have one header file that includes all of the Standard Library headers that you are using in your project. It makes precompilation easier, makes it easier to port to a non-standard environment, and also helps deal with those issues that sometimes arise when headers are included in different orders in different source files. But that header file should be explicitly included by each source file; there should be no magic.)


Forget the compilation speed-up - a precompiled header with templates isn't really "precompiled" except for the name and the parse, as far as I've heard. I won't believe in the compilation speed up until I see it in the benchmarks. :)

As for the usefulness:

I prefer to have an IDE which handles my includes for me (this is still bad for C++, but Eclipse already adds known includes with ctrl+shift+n with... well, acceptable reliability :)).


Doing 'clandestine' includes like this would also make testing more difficult. You want to compile a smallest-possible subset of code when testing a particular component. Figuring out what that subset is would be difficult if the headers/sources aren't being honest about their dependencies, so you'd probably just drag your my_cpp_std_lib_hack into every unit test. This would increase compilation time for your test suites a lot. Established code bases often have more than three times as much test code as regular code, so this is likely to become an issue as your code base grows.


From the GCC manual:

-include file

Process file as if #include "file" appeared as the first line of the primary source file. However, the first directory searched for file is the preprocessor's working directory instead of the directory containing the main source file. If not found there, it is searched for in the remainder of the #include "..." search chain as normal.

So what you're doing is essentially equivalent to starting each file with the line

#include "my_cpp_std_lib_hack"

which is what Visual Studio does when it gathers up commonly-included files in stdafx.h. There are some benefits to that, as outlined by others, but your approach hides this include in the build process, so that nobody who looked directly at one of your source files would know of this hidden magic. Making your code opaque in this way does not seem like a good style to me, so if you're keen on all the precompiled header benefits I suggest you explicitly include your hack file.


You are doing something very wrong. You are effectively including lots of headers that may not be needed. In general, this is a very bad idea, because you are creating unnecessary dependencies, and a change in any header would require recompilation of everything. Even if you are avoiding this by using precompiled headers, you are still linking to lots of object that you may not need, making your executable much larger than it needs to be.

There is really nothing wrong with the standard way of using headers. You should include everything you are using, and no more (forward declarations are your friends). This makes code easier to follow, and helps you keep dependencies under control.


We try not to include the unused or even the rarely used stuff for example in VC++ there is

#define WIN32_LEAN_AND_MEAN //exclude rarely used stuff

and what we hate in MFC is that if u want to make a simple application u will produce large executable file with the whole library (if statically linked), so it's not a good idea what if u only want to use the cout while the other no??

another thing i don't like to pass arguments via command line coz i may leave the project for a while, and forget what are the arguments... e.g. i prefer using

#pragma (comment, "xxx.lib")

than using it in command line, it reminds me at least with what file i want

That's is my own opinion make your code stable and easy to compile in order to to rot as code rotting is a very nasty thing !!!!!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜