- Forward declarations can hide a dependency, allowing user code to skip necessary recompilation when headers change.
- … Replacing an #include with a forward declaration can silently change the meaning of code …
I think each one of those two is very nasty on its own.
The first one would just result in link errors instead of compile errors. Not especially nasty as far as I can see. The second one seems like FUD. Is there a realistic example of this happening? Could the example happen accidentally, or would you have to go out of your way to engineer an it like in void* inheritance case? If this could happen accidentally, would basic sentient human code review or use of “grep” catch it?
There are practical benefits to using simple forward declarations like the non-template non-typedef non-std:: ones I write myself, or the ones created by the IWYU tool. Obviously there are specific situations where forward declarations are bad to use and the google style guide covers them well. But there is no reason to throw out the baby with the bathwater with another one of these “X considered harmful” proclamations. Especially since unlike other X’s, you can’t actually get rid forward includes if you want to write type-safe modular code.
I will also say that I like the use of forward declarations aesthetically and semantically. An include says “the code in this file depends on this code in this other file”. A forward declaration when it is properly used (something enforceable by IWYU) says “the code in this file does NOT depend on this type, and is just letting code in two other files that do you use the type communicate safely.”