Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Managing forward declarations

It's well known that using forward declarations is preferable to using #includes in header files, but what's the best way to manage forward declarations?

For a while, I was manually adding to each header file the forward declarations that were needed by that header file. However, I ended up with a bunch of header files repeating the same half-dozen or so forward declarations, which seems redundant, and maintaining these repeated lists got to be a bit tedious.

Forward declarations of typedefs (e.g., struct SensorRecordId; typedef std::vector<SensorRecordId> SensorRecordIdList;) is also a bit much to duplicate across multiple header files.

So then I made a ProjectForwards.h file that contains all of my forward declarations and included that wherever it was needed. At first, this seemed like a good idea - much less redundancy, and much easier maintenance of typedefs. But now, as a result of using ProjectForwards.h so heavily, whenever I add a new class to it, I have to rebuild the world, which slows development.

So what's the best way to manage forward declarations? Should I bite the bullet and repeat individual forward declarations across multiple subsystems? Continue with the ProjectForwards.h approach? Try to split ProjectForwards.h into several SubsystemForwards.h files? Some other solution I'm overlooking?

like image 850
Josh Kelley Avatar asked Feb 07 '12 16:02

Josh Kelley


People also ask

What is forwarding declaration?

In computer programming, a forward declaration is a declaration of an identifier (denoting an entity such as a type, a variable, a constant, or a function) for which the programmer has not yet given a complete definition.

Where do you put forward declaration?

Generally you would include forward declarations in a header file and then include that header file in the same way that iostream is included.

Is forward declaration good practice?

The Google style guide recommends against using forward declarations, and for good reasons: If someone forward declares something from namespace std, then your code exhibits undefined behavior (but will likely work).

What is the advantage of forward declaration?

Forward declarations in C++ are useful to save in compile time as the compiler does not need to check for translation units in the included header. Also it has other benefits such as preventing namespace pollution, allowing to use PImpl idiom and it may even reduce the binary size in some cases.


1 Answers

It sounds like these classes are fairly common to much of your project. You might try some of these:

  • Do your best to break apart ProjectForwards.h into several files as you suggested. Make sure each subsystem only gets the declarations it truly needs. If nothing else, that process will force you to think about the coupling between your subsystems and you might find ways to reduce it. These are all good steps toward avoiding over-compilation.

  • Mimic <iosfwd>. Have each common class or module provide its own forward-include header that just provides the class names and any convenience typedefs. Then you can #include that everywhere. Yes, you'll repeat the list a lot, but think about it this way: nobody complains about #including <vector>, <string>, and <map> in six different places in their code.

  • Use Pimpl more often. This will have a similar effect to my previous suggestion but will require more work on your part. If your interfaces are stable, then you can safely provide the typedefs in those headers and #include them directly.

like image 54
Michael Kristofik Avatar answered Sep 21 '22 06:09

Michael Kristofik