1

It is quite common to separate C++ code into cpp and hpp files and to define the hpp files as the interface of the code. Therefore, when you use the code as a library, you can expose the interface, but offer the rest as a compiled library. It also allows to separate different components of the code in a way that one component can access other components' interfaces without needing access to the core code (and potentially need access to all its dependencies).

Are there any reasons why interfaces should not contain cpp files?

I could put the cpp code into the hpp file of course, but if the file contains a lot of definitions, those would be copied by the preprocessor for each #include of that file.

My first instinct was to keep the files separate and use both the hpp and cpp in the interface.

One issue I could imagine is this:

If I compiled my component to a lib, then the interface cpp would be compiled into the lib as well, but it would also be shipped as part of the interface. I tried this with a minimal example and the linker does not complain about having a definition in the cpp and the same definition in the lib.

So apparently this could lead to problems if the cpp and the lib were to become inconsistent. In my minimal example, the compiler uses the version from the cpp and not the one compiled into the lib, so this could become a problem of expected behavior: The recipient of the interface would get what they see in the cpp file, but the person who compiled the lib could have had a different behavior in mind.

This makes me think that having cpp files in the interface is inherently dangerous. Am I right with this line of reasoning or are there examples where it makes sense to do this?

5
  • 1
    By "interfaces", do you mean the distributed part of a library? It is common to distribute the whole source of a library, so that the end user can ensure it is binary compatible, by compiling it all themselves
    – Caleth
    Nov 29, 2021 at 15:34
  • 1
    Header-only libraries are quite common. The test you should apply is "is this a definition of a symbol of which I only want one copy in the resulting binary?" (function definition, global variable definition). Those go in the cpp.
    – pjc50
    Nov 29, 2021 at 17:08
  • @Caleth Yes, pretty much, but I wanted to explicitly avoid having to distribute all my sources to keep things simple. So the question is specifically about whether I could do a hpp/cpp split like with the core code, or whether it's better to have a single large hpp file.
    – Cerno
    Nov 30, 2021 at 0:42
  • @pjc50 That's a hint in the right direction, I guess. So since a split of hpp/cpp for an interface file would definitely create a second copy like I described in the post (one in the compiled lib and one in the compiled binary that includes the lib), I guess I shouldn't do the split and just use a single larger hpp file.
    – Cerno
    Nov 30, 2021 at 0:44
  • 1
    @Cerno the simple thing is to distribute your source. It is much more complex to build your library with every combination of compiler and settings that your users will use, and distribute all those resulting binaries
    – Caleth
    Nov 30, 2021 at 10:06

1 Answer 1

3

Are there any reasons why interfaces should not contain cpp files?

Those reasons mostly come down to common conventions.

The compiler (or, to be more precise, the preprocessor) will happily process a #include <my-file.cpp> directive. The file extension does not have any intrinsic meaning there.

On the other hand, it is conventional that .cpp files do not contain protection mechanisms against being #included multiple times (like #pragma once) and it is a file that can contain definitions of which the linker should see only a single copy.

And it is conventional to have shared declarations and definitions that are allowed to occur multiple times in .h or .hpp files (and template implementations in .tcc files, although that is less common)

If your idea to include a .cpp file in the interface comes from the feeling that your .hpp file is growing too big, then you can also split your .hpp file in multiple parts and maybe use a different file extension (like the .tcc mentioned above) for the files containing implementation details.

1
  • Thanks for your input. I would definitely want to avoid #including a cpp file because I don't want to break the convention of compiling the cpp file into an obj file while the hpp file is classically only copied via #include and added inline to each compilation unit. The idea of using a .tcc file (or .inl file as I know it), seems sensible in order to structure the code better. Thanks.
    – Cerno
    Nov 30, 2021 at 9:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.