5

I ran into a situation where my build speeds have started to become large and have affected productivity. I had already minimized header dependencies before using forward declarations. Now I've turned to forward declarations to further reduce these dependencies as a method of trying to reduce compile times.

I understand the concept of forward declarations, but I didn't quite understand how much you could forward declare until I came across this. As I understand it, I can forward declare all method/function parameter and return types for function declarations.

I have a lot of situations where I have (assume I have include guards in header):

//myclass.h
#include "someclass.h"
#include "someotherclass.h"

class MyClass{
public:
    SomeOtherClass foo(SomeClass y);
};

With forward declarations, I can now do something like:

//myclass.h
class SomeClass;
class SomeOtherClass;

class MyClass{
public:
    SomeOtherClass foo(SomeClass y);
};
//include actual header files in myclass.cpp

I believe this will require the header to be included at the call site some how, but removes the include from the header. And the caller doesn't use that call, I would assume It would just be a net gain of needing that dependency at all on the call site.

I haven't seen this pattern before (only with class members and private function types), so I'm wondering if there is any downside to doing this. Is there a reason why I shouldn't just forward declare all of these types?

  • 1
    @DocBrown My concern is that there is some non compiler related reason why I might want to avoid this. I've never seen a library which didn't include the types necessary to run the functions it defines, at least not on public facing functions. Is there an argument made to the usability cost of creating all of these incomplete types required to run library functions? – opa Mar 20 at 21:37
  • Naive question: instead of spending expensive time on reengineering declarations,wouldn’t it be more productive to invest in more performant hardware ? – Christophe Mar 21 at 8:46
  • I feel this is a badly phrased question. By asking it so specifically in the negative you are preventing people from giving the best answers to the question: you should forward declare by default and avoid it only in rare situations. There are reasons not to but they're not sufficient to recommend against. – Jack Aidley Mar 21 at 9:25
  • I can't advise against their usage despite what Google Style Guide says. – R Sahu Mar 23 at 5:50
  • 1
    Related: stackoverflow.com/q/9906402/509868 – anatolyg Mar 28 at 12:26
10

Yes, at least one reason exists.

The Google Style Guide acknowledges that forward declarations can improve compile time, but still advises developers to prefer #include declarations when possible (especially when using third-party libraries), and lists some reasons why:

  • Forward declarations can hide a dependency, allowing user code to skip necessary recompilation when headers change.
  • A forward declaration may be broken by subsequent changes to the library. Forward declarations of functions and templates can prevent the header owners from making otherwise-compatible changes to their APIs, such as widening a parameter type, adding a template parameter with a default value, or migrating to a new namespace.
  • Forward declaring symbols from namespace std:: yields undefined behavior.
  • It can be difficult to determine whether a forward declaration or a full #include is needed. Replacing an #include with a forward declaration can silently change the meaning of code.
  • Forward declaring multiple symbols from a header can be more verbose than simply #includeing the header.
  • Structuring code to enable forward declarations (e.g. using pointer members instead of object members) can make the code slower and more complex.

There are, of course, dissenting opinions elsewhere on the Web. Most reasonable[citation needed] treatments of the subject admit there are benefits and drawbacks to either approach, and so, as usual, it's a judgment call whether to use or not use this tool in any given situation.


These are not the only articles written on the subject, nor are they authoritative. They're just two relevant pages I happened to stumble across (one of them being a response to the other); there is of course a much wider debate to be found, if you care to look.

This answer was written primarily by just copying information from other sites. The search terms I plugged into Google were:

"c++" "do not use forward declarations"

This got me a decent list of sites on page 1 that could be skimmed to pick out what the conventional wisdom might indicate are the pros and cons of this language feature.

You can try these and other terms and search query formats to find controversy over the use of lots of other optional language tools, too; my personal favorite currently happens to be generics (if they're in Go 2, I will continue using Go 1 as long as it's still supported, and then probably find a different favorite language).

  • 10
    Generally, citing the Google Style Guide as an authority for anything will incite controversy, as many with good reason see it as an unconscionable violation of any attempt to write good code. At least, in this case the decision section is acceptable, even if it can be summarized thus: Only forward-declare entities from the same project, and even then sparingly. As an attempt at properly representing it, you should have included the other two sections (Pros+Decision), which as shown makes this point more reasonable. – Deduplicator Mar 20 at 22:46
  • 1
    I agree it's controversial (and for that reason included a dissenting opinion even though it doesn't directly help answer the question that wasn't asked). I think I disagree with the decision, even though I haven't needed to care that much in a while (my current team uses Go in all the places we might've otherwise used C++). Still, in the interest of answering "are there any reasons not to...?", a popular(-ish) guide listing those reasons seems like a relevant link to me. ¯_(ツ)_/¯ – Jesse Amano Mar 20 at 22:51
  • Good point re: editing in the decision summary. I did not paraphrase it well on my first attempt. – Jesse Amano Mar 20 at 22:53
  • 4
    Most points in that Google Style Guide are very weak or strawman arguments, especially the one about undefined behaviour. – Christian Hackl Mar 21 at 6:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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