-2

For example, from my basic understanding of C++ and clang++, I don't understand why the following setup wouldn't be preferable:

It seems like using the variation with headers would produce more output, needs a more specific compiler setup, and needs duplicity in declaration of functions.

clang++ --std=c++2a Start.cpp -o Start.o; ./Start.o

Start.cpp

#include "A.cpp"
#include "B.cpp"

int main (
    int argc,
    char** argv
) {
    A();
    B();

    return 0;
}

A.cpp

#ifndef A_H
#define A_H

#include <stdio.h>
#include "C.cpp"

void A() {
    printf("A\n");
    C();
}

#endif

B.cpp

#ifndef B_H
#define B_H

#include <stdio.h>
#include "C.cpp"

void B() {
    printf("B\n");
    C();
}

#endif

C.cpp

#ifndef C_H
#define C_H

#include <stdio.h>

void C() {
    printf("C\n");
}

#endif
Bryan Grace
  • 1,826
  • 2
  • 16
  • 29
  • 1
    Shouldn't you be including .h files not .cpp files? This isn't PHP :) – Dave S Feb 25 '20 at 00:25
  • 2
    You should not be `#include`'ing `.cpp` files to begin with. Specify them on the command-line instead. Or change them into `.h` files, which is what you appear to have wanted in the first place – Remy Lebeau Feb 25 '20 at 00:25
  • 4
    OP, your question is confusing (see comments above). Your title is about include guards, but really your question is about single-translation-unit compilation vs multiple-translation-unit compilation. – walnut Feb 25 '20 at 00:26
  • 3
    Does this answer your question? [#include all .cpp files into a single compilation unit?](https://stackoverflow.com/questions/543697/include-all-cpp-files-into-a-single-compilation-unit) and [Why have header files and .cpp files?](https://stackoverflow.com/questions/333889/why-have-header-files-and-cpp-files) – walnut Feb 25 '20 at 00:30
  • @walnut Ok so it possibly can speed up the linking of the e.g. "Start" program... – Bryan Grace Feb 25 '20 at 01:04
  • 3
    normally `.o` file extension is used for object files, not executables – M.M Feb 25 '20 at 01:29
  • 1
    This is called a "[unity build](https://onqtam.com/programming/2018-07-07-unity-builds/)". They're not very popular, but they can work quite well. – David Schwartz Feb 25 '20 at 02:23

1 Answers1

2

If you link that object file with another one that has included one of the cpp files, the program would violate One Definition Rule because those files contain definitions of non-inline functions.

Also, it is conventional to compile cpp files and link them together. If you both compile any of those cpp files, while also including it into another translation unit, you will encounter that ODR violating scenario.

To solve this problem, if you include a file into other files, then you generally should ensure that the included file (i.e. header file) doesn't contain anything that would violate ODR when included into multiple translation units.

Also, it is a best practice to conform to a commonly used naming scheme. Using cpp extension for header files is contrary to all common naming schemes.

Is there a good reason to use include guards in h files instead of cpp files?

You should always use include guard in all header files, regardless of how you name the header files. (although technically the header guards are not needed in some headers, but it is easier to simply use a header guard than keep track of whether you need it or not).


Now, if you were wondering whether you could put all your function definitions into a single translation unit: Yes, you can. This has advantages and disadvantages:

Advantage of single TU: Faster compilation time from scratch due to no repetition of compiling templates and other inline functions. Also better optimisation because there are no translation unit boundaries that would prevent optimisation - this advantage is diminished by link time optimisation which works across TU boundaries.

Disadvantage: Any change to a program only causes recompilation of the modified translation units. When there is only one translation unit that is the entire program, then any change, no matter how small, will require recompilation of the entire program. This is highly undesirable. This disadvantage is diminished by link time optimisation which can cause linking to be so slow that time saved from reused translation units can become insignificant.

eerorika
  • 232,697
  • 12
  • 197
  • 326