in the header where A is defined, I can write class B; to avoid including the header file declaring B.
But what for typedef:
if A is:
class A { void f(tB* pB) {}
};
if I write class tB; in A.h, I have the follwing compiler error: error C2371: 'tB' : redefinition; different basic types, because a typedef is not a class.
I tried several syntax, but finally, is it possible to declare a typedef like we do for a class?
> if I write > class tB; > in A.h, I have the follwing compiler error: > error C2371: 'tB' : redefinition; different basic types, because a > typedef is not a class.
> I tried several syntax, but finally, is it possible to declare a > typedef like we do for a class?
> Thanks for help.
First off, use a const reference or a reference instead of a pointer. Typedef's are not neccessarily usefull. If you don't show compileable code, we can only guess at your problem. Guessing is bad, very bad. Use include guards, as follows:
On Aug 20, 10:50 pm, nguillot <nicolas.guil...@gmail.com> wrote:
> [snip] I can write > class B; > to avoid including the header file declaring B.
You can but you shouldn't, despite lots of generally respected authors recommending it.
If the developer of the header declaring B thinks including the header imposes (or may one day impose) a significant performance penalty, they should provide a forward-declaration header (e.g. <iosfwd> instead of <iostream>). If they haven't provided such a header, and you can't talk them into doing so, and you're working on a non-trivial project with many source files using their header, then you can create and maintain a single forward-declaration header yourself. Still painful, but at least centralised.
Declaring things that the B-developer is quite entitled to change at any time (e.g. from a class to a typedef to a template instantiation) is as bad as the olden-days habit of not using headers, and having extern declarations for the extra-translation-unit functions you plan to call....
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.
> in the header where A is defined, I can write > class B; > to avoid including the header file declaring B.
> But what for typedef:
> if A is:
> class A > { > void f(tB* pB) {} > };
> if I write > class tB; > in A.h, I have the follwing compiler error: > error C2371: 'tB' : redefinition; different basic types, because a > typedef is not a class.
> I tried several syntax, but finally, is it possible to declare a > typedef like we do for a class?
On Wed, 20 Aug 2008 12:48:03 -0700 (PDT), tony_in_da...@yahoo.co.uk <tony_in_da...@yahoo.co.uk> wrote: > On Aug 20, 10:50 pm, nguillot <nicolas.guil...@gmail.com> wrote: >> [snip] I can write >> class B; >> to avoid including the header file declaring B.
> You can but you shouldn't, despite lots of generally respected authors > recommending it.
...
> Declaring things that the B-developer is quite entitled to change at > any time (e.g. from a class to a typedef to a template instantiation) > is as bad as the olden-days habit of not using headers, and having > extern declarations for the extra-translation-unit functions you plan > to call....
Unlike that old pain, a "class B;" in my code cannot silently cause my program to stop working, can it?
> 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.
To answer the original question a bit: I think the problem he sees with typedefs is a reason many people prefer not to typedef classes.
> in the header where A is defined, I can write > class B; > to avoid including the header file declaring B.
> But what for typedef:
> if A is:
> class A > { > void f(tB* pB) {}
> };
> if I write > class tB; > in A.h, I have the follwing compiler error: > error C2371: 'tB' : redefinition; different basic types, because a > typedef is not a class.
> I tried several syntax, but finally, is it possible to declare a > typedef like we do for a class?
Well... You say theerror is in A.h. But, I'md doubting it. I'm thinking the error is actually in some .CPP file that includes the A.h header.
This would seem to indicate that some .CPP file includes both A.h and B.h.
As others have said, you want to resist this scheme. If you absolutely need it, can't do without it, then...
So what to do about that? Well, clearly what you need is some kind of include guard. Getting down to the level of individual typedefs is, maybe, a little finicky.
But as somebody suggested, you want a Bfwd, or forward defn header. And it gets its own include guards. If you have control of both B.h and A.h then you can have B.h include Bfwd.h for the typedef, and that way make sure it is identical in both B.h and A.h.
And that gets you past the gnarly possible things that might happen if the class B changes. Socks
I don't see why typedef B tB; is ugly. If B is std::map<std::string, std::.....> the typedef is worth. With the typedef I can write tB::iterator, instead of std::map<std::string, std::.....>::iterator. And it factorizes the code.
About providing compileable code, so you only can guess... Do you really think it's a problem. I guess the problem was explain (and the problem is not about pointer or reference), it's about including header or forwarding declarations; and how to forward the declaration of a typedef. Not more about protecting header with the guard #ifdef... But sorry if my question was not clear.
My main question was indeed (but I learned the correct vocabulary by reading your answers): how to forward declare a typedef.
About using headers instead of forward declaration, I guess it's a real debate. Good authors defend one way or the other.
For my problem, I would need this forward declaration to decrease the compilation time (really decrease!). A.h as B.h are my code, I have access to it.
So because it's really worth to decrease compilation time, the solution would to provide a forward header... I'll try that way.
On Aug 22, 1:30 am, Jorgen Grahn <grahn+n...@snipabacken.se> wrote:
> 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 T> class XT {...}; typedef XT<int> X;", 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.