I've been looking at Boost and various other C++ libraries. The vast majority of Boost is implemented in header files.
My question is: under what conditions do you do a header-only implementation (like Boost) or also include a .cpp file?
I've been looking at Boost and various other C++ libraries. The vast majority of Boost is implemented in header files.
My question is: under what conditions do you do a header-only implementation (like Boost) or also include a .cpp file?
If you want to use a template in another translation unit (i.e. another source file), you should (almost always) define it in the header file. (There are exceptions, like the comments below point out, but IMHO this is a good rule of thumb.)
Same applies if you want to use an inline function from another translation unit.
Otherwise you should put the implementation into a separate .cpp file to minimize dependencies.
Understanding this issue is basically about understanding how C++ compilation units work. Things in header files are basically pasted into the source code of a whole bunch of compilation units by #include
statements. Each compilation unit gets compiled into an object file, the object files get linked, and you get conflicts because of that stuff being replicated all over the place.
The exceptions are things that (historically, at least) don't go into the object file because the compiler deals with them directly (e.g. inline functions), and things that can't be compiled in one unit then linked to another because they aren't completely defined (templates). Template functions often get identically instantiated in multiple compilation units, and the linker has special smarts to discard the duplicates.
This means that the separation of interface and implementation into header and body files isn't as very clean. Ada has a much cleaner separation - but a more complex build process to compensate IIRC. Java simply dropped the separate files for interface and implementation thing.
Linkers have got a lot more sophisticated over the years and taken over some of the work of the compiler, and a lot of this explanation is simply wrong these days, yet the basic patterns remain. Template functions and inline functions can (and often need to) go in the header, along with all your don't-directly-generate-object-code shared declarations. Normal function definitions should not be in a header file.