From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,18f6de557e6897b2 X-Google-Attributes: gid103376,public X-Google-Thread: 109fba,75227fc9e75eca6b,start X-Google-Attributes: gid109fba,public From: "John G. Volan" Subject: Ada95 packages, C++ namespaces, & circular dependencies Date: 1997/06/04 Message-ID: <33964782.1DEC@sprintmail.com> X-Deja-AN: 246230222 References: <3386d96f.171920@noticias.ibernet.es> <33898C78.27D3@sprintmail.com> <33937420.4458@sprintmail.com> Organization: Sprint Internet Passport Reply-To: johnvolan@sprintmail.com Newsgroups: comp.lang.ada,comp.lang.c++ Date: 1997-06-04T00:00:00+00:00 List-Id: David Weller wrote: > > John, > here's an interesting thought. WIth the advent of namespaces in C++, > which generally mimic packages (the "old" non-child type a la Ada83), ^^^^^^^^^^^^^^^^^^^^^^^^ See [***] NOTE: below > what is the result of mutual dependencies on classes in separate > namespaces? I wonder if that has an effect in C++? I don't know if > you've pondered that one or not. ----- I'm cross-posting this to comp.lang.c++, because it's pertinent, and because I would like to get some confirmation on my understanding of C++. For those of you on comp.lang.c++, here's the background on this thread: I've written up an FAQ concerning an apparent "hole" in the design of Ada95 known as the "with-ing" problem, which has to do with circular dependencies between packages. You can find this FAQ at the following URL: http://bluemarble.net/~jvolan/WithingProblem/FAQ.html You might want to peruse this before reading further. In particular, section [5.4] compares proposed Ada0Y solutions for this problem with the current situation in C++ http://bluemarble.net/~jvolan/WithingProblem/FAQ.html#cplusplus Please do not use this thread as an excuse for Ada-bashing. In comparing Ada95 with C++, I've tried to be fair to both languages. Please extend the same courtesy. ----- Here's my response to David Weller: It's only been in the past couple days that I've managed to find the URL for the online C++ draft standard working paper http://www.maths.warwick.ac.uk/c++/pub/wp/html/cd2/ and read the straight dope on namespaces. From what I can glean from the verbiage there, it doesn't look like namespaces introduce any new problems for C++ with regard to separate encapsulation/mutual dependency. In fact, to me they seem most reminiscent of Norman Cohen's "package parts" idea for Ada0Y. It appears that you can scatter as many sections of the same namespace as you want through any given C++ compilation. So, for instance, you could have the following (but see the [**] DISCLAIMER below). // let this be all in one file, or perhaps all in // one output from the C++ preprocessor: namespace Doctors { // initial definition of namespace class Doctor; // forward class declaration } namespace Patients { // initial definition of namespace class Patient; // forward class declaration } ... namespace Doctors { // extension providing "interface" class Doctor { // full class declaration ... public: ... void treatPatient (Patients::Patient& patient); void billPatient (Patients::Patient& patient); ... }; } namespace Patients { // extension providing "interface" class Patient { // full class declaration ... public: ... void visitDoctor (Doctors::Doctor& doctor); void payDoctor (Doctors::Doctor& doctor); ... }; } ... //----- See [*] NOTE: below. ----- namespace Doctors { // extension providing "implementation" // definitions of Doctor member functions: void Doctor::billPatient (Patients::Patient& patient) { ... Doctor& doctor = *this; patient.payDoctor (doctor); } ... } namespace Patients { // extension providing "implementation" // definitions of Patient member functions: void Patient::visitDoctor (Doctors::Doctor& doctor) { ... Patient& patient = *this; doctor.treatPatient (patient); } ... } This arrangement seems a lot like my "package abstracts" proposal (see section [5.1] of my FAQ, at URL: http://bluemarble.net/~jvolan/WithingProblem/FAQ.html#abstracts It also appears that namespace sections can be sliced up and scattered through as many source files as you wish. Remember that C++ still does not define any notion of "semantic dependency" between "compilation units" comparable to Ada's "with" clauses (at least, as near as I can tell). All it provides is a mechanism for preprocessor textual inclusion between source files. It's up to the programmer to make sure that the source files that are #included into a given compilation get assembled into some kind of meaningful order within the preprocessor, before being fed into the compiler proper. And it's still up to the programmer to specify what object files go into a link, and to ensure that those object files are semantically consistent with each other--or at least they are all based on the same versions of the same #included source files (usually with assistance from some tool outside the language, e.g. "make"). But this allows a C++ programmer to do something like the following: //////////////////////////////////////////////////////////// // Doctors_forward.h //////////////////////////////////////////////////////////// #ifndef _DOCTORS_FORWARD_H #define _DOCTORS_FORWARD_H namespace Doctors { // initial definition of namespace class Doctor; // forward class declaration } #endif _DOCTORS_FORWARD_H //////////////////////////////////////////////////////////// // Doctors.h //////////////////////////////////////////////////////////// #ifndef _DOCTORS_H #define _DOCTORS_H #include "Doctors_forward.h" #include "Patients_forward.h" ... // other *_forward.h inclusions namespace Doctors { // extension providing "interface" class Doctor { // full class declaration ... public: ... void treatPatient (Patients::Patient& patient); void billPatient (Patients::Patient& patient); ... }; } #endif _DOCTORS_H //////////////////////////////////////////////////////////// // Doctors.cc //////////////////////////////////////////////////////////// #include "Doctors.h" #include "Patients.h" ... // other *.h inclusions namespace Doctors { // extension providing "implementation" // definitions of Doctor member functions: void Doctor::billPatient (Patients::Patient& patient) { ... Doctor& doctor = *this; patient.payDoctor (doctor); } ... } The source files for the sections of the Patients namespace would be similar. [*] NOTE: The sequence of #include directives in the Doctors.cc file #include "Doctors.h" #include "Patients.h" when textually expanded in the C++ preprocessor, would generate the interleaving of Doctors and Patients namespace sections I showed above, up to the "See [*] NOTE:" comment. The sequence of #includes that might appear in the Patients.cc file #include "Patients.h" #include "Doctors.h" would generate a similar interleaving, but with the corresponding Doctors and Patients sections interchanged. Both interleavings should compile successfully. It just goes to show you: It really doesn't matter whether the chicken comes first, or the egg! :-) [**] DISCLAIMER: The Doctors/Patients namespace example above is a bit contrived. I'm not sure you'd want to bother wrapping e.g. a "Doctor" class inside a "Doctors" namespace, since the class itself, being a kind of module as well as a type, already provides a level of scope analogous to a "Doctors" package containing a "Doctor_Type". A more realistic scenario might be to use a namespace for a subsystem, with various classes nested inside it (but possibly scattered over many source files). For instance, you might have a "Providers" subsystem implemented as a namespace, with "Doctor" as one of the classes inside it; likewise, a "Consumers" subsystem as a namespace, with "Patient" as one of the classes inside it.) [***] NOTE: David, I think you may be underestimating what namespaces can do. Because you are allowed to extend a namespace as many times as you like within a given compilation, and because the C++ preprocessor can stitch together a compilation from any arbitrary set of source file inclusions, it looks like namespaces will in fact be able to mimic the functionality of Ada95 child hierarchies after all. ------------------------------------------------------------------------ Internet.Usenet.Put_Signature (Name => "John G. Volan", Employer => "Texas Instruments Advanced C3I Systems, San Jose, CA", Work_Email => "johnv@ti.com", Home_Email => "johnvolan@sprintmail.com", Slogan => "Ada95: World's *FIRST* International-Standard OOPL", Disclaimer => "My employer never defined these opinions, so using" & "them would be totally erroneous ... or is that" & "just nondeterministic behavior now? :-) "); ------------------------------------------------------------------------