2

I found several places where it is discussed whether it is better to put definitions in headers or not (e.g. here). However, I could not find something like a "guide to header-only code". The answer to the linked question mentions some downsides:

  • increased compile time
  • not possible to have circular dependencies
  • no (simple) global objects

But is that all?

What are the consequences of putting (all) code in the header?

Am I save if I use header guards, or are there other pitfalls?

The reason I am asking this is the following: I am in a situation where I think it would easiest to put all the code in my header files. It is a (rather small) collection of classes and functions that is supposed to be included by others in their code. It is supposed to be used in different environments and in different frameworks. At the moment, I do not see why I should build my code (into a lib), when the one using it can simply include the header she/he needs and compile it. However, independent of this project I always have a "bad feeling" when putting code in headers, even if none of the 3 points I mentioned above matters. Would be really nice if someone could shed some light on this for me so I can make the decision where to put the code on a more reasonable basis.

Community
  • 1
  • 1
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185

2 Answers2

3

There are several examples of brilliant libraries implemented mostly in header files, e.g. the std library or boost. In particular, if you want to distribute a template library, you have you have no real alternative.

Worst consequences of such an approach, imho, are:

  • exploding of compilation time: every edit you make to your code, you'll have to rebuild all files that include that header; this is a really serious issue, unless you keep using the ".h"/".cpp" approach while developing and then rearrange your code into the header just at the end
  • binary code bloat: all your functions will have to be declared "inline", so you may have a performance improvement but you may (1) also have a replication of binary code every time you use a function

(1) see Klaus comment and inline description at cppreference.com (quoted below):

The intent of the inline keyword is to serve as an indicator to the optimizer that inline substitution of the function is preferred over function call, that is, instead of executing the call CPU instruction to transfer control to the function body, a copy of the function body is executed without generating the call. This avoids extra overhead created by the function call (copying the arguments and retrieving the result) but it may result in a larger executable as the code for the function has to be repeated multiple times. Since this meaning of the keyword inline is non-binding, compilers are free to use inline substitution for any function that's not marked inline, and are free to generate function calls to any function marked inline. Those choices do not change the rules regarding multiple definitions and shared statics listed above.

Community
  • 1
  • 1
Paolo M
  • 12,403
  • 6
  • 52
  • 73
  • 1
    I absolutely disagree about code bloat! My experience is, that the inlining goes ahead with constant calculation and propagation which mostly results in "optimized away" parameters and functions. With c++11 and constexpr this effect is much higher then the doubling of executed code in inlines. – Klaus Jun 11 '15 at 10:46
  • @Klaus Really interesting! I think that, depending on several factors like "length" of the function and others, one may have different behaviors. What do you think? – Paolo M Jun 11 '15 at 10:52
  • 1
    can you elaborate a bit more on inline? I am always a bit confused about "inline = function defined in the header" and "inline = function with the inline keyword" (which is only valid if the function is defined in the header, right?) – 463035818_is_not_an_ai Jun 11 '15 at 11:09
  • @tobi303 Added a description of the inline specifier. For a full reference, follow the link in my answer ;) – Paolo M Jun 11 '15 at 11:15
  • hm sorry, but now I am a bit more confused... before I thought in your second point with "inline" you refer in general to functions defined in the header (with or without the inline keyword). – 463035818_is_not_an_ai Jun 11 '15 at 11:20
  • @tobi303 The inline specifier has several purposes. Beyond what I've quoted, there is the following one: "There may be more than one definition of an inline function in the program as long as each definition appears in a different translation unit. For example, an inline function may be defined in a header file that is #include'd in multiple source files." – Paolo M Jun 11 '15 at 11:29
  • I just had my first use case of the mentioned code and now I understand that I have to declare any "free" (i.e. non-class member) function as inline otherwise there will be linker errors (multiple definitions). For class methods, I do not have to use the inline keyword, but I guess they are still called "inline" when defined in a header. – 463035818_is_not_an_ai Jun 11 '15 at 15:39
  • @tobi303 Yes they are. And you must declare them inline too, if you define them in the header outsider of the class declaration. – Paolo M Jun 11 '15 at 18:10
3

Starting from my personal experience, I usually put only one-line functions (getters and setters) in the header file because all other function bodies will make the header file difficult to read and understand at a glance. Moreover if your project needs to include the header file multiple times (and you wrote function code in it), you would have an icreasing compile times since all code has to be processed every time it is included by the compiler.