On Aug 22, 1:30 am, Jorgen Grahn <grahn+n...@snipabacken.sewrote:
Unlike [embedded extern fn declarations], a "class B;" in my code
cannot silently cause my program to stop working, can it?
Depends who you are in the software system, what you call silently and
working, and what expectations and responsibilities you feel different
developers involved can have of and to each other.
As a library developer defining a class X in a header, I would argue
that you are entitled to replace it with "template <typename Tclass
XT {...}; typedef XT<intX;", as well-written client code that
includes your header will seamlessly recompile and work. This is
standard practice when evolving code is generalised to arbitrary
types.
But - silently from the perspective of the library developer who
doesn't necessarily know about all client usage or trigger client app
recompilation - poorly-written client code hard-coding "class X;" will
break. Scenario: Some production issue requires a urgent bug fix and
instead the app developer finds unrelated parts of their app aren't
compiling any more and must be fixed simultaneously, delaying
deployment of the fix. If the library developer considers their
clients as part of their overall "system" (a responsible attitude and
generally expected in corporate life at least), then yes their change
broke their system. But they're not really to blame....
Can it be worse? Probably. Thinking about all the combinations of
layers of objects, headers, static vs load-time vs run-time binding
etc. does my head in and I'd need a better reason for suffering that
than this thread.
About the best that can be said is that at least some of these issues
differ from extern function abuses, where the consequences are more
consistently in the SIGSEGV category ;-).
To make the most of your build tools (e.g. make), you have to work in
with their logic about recompilation, not fight it with hacks.
Changes with compatible usage should trigger a rebuild.
I take it that is your main argument against forward declarations.
I disagree, at least in the case where I am the author of class B and
can change both B and the code which uses it whenever needed.
Bringing down compilation times is worth a lot, in my opinion. I also
prefer my code seeing as few names as possible, even if everything is
in namespaces and there are no macros with too generic names.
Forward declaration headers - maintained by the downstream library -
are the only proper way to handle this. If a header pulls in myriad
other headers AND has many independent parts then it's a strong
candidate for separation into multiple headers / forward-declaration
pairs, with the original header including the parts. This way
upstream clients can select those parts that are useful without the
full burden of including extra headers. pImpl / envelope-letter
idioms help. If managed maturely, the compilation times can almost
always be kept thoroughly under control and don't begin to justify the
complications of the "class X;" hack.
Tony