Categories
Computers & Software Electrophysiology

Namespace Blues

I spent the weekend not writing code, but thinking about how to organize my code. EP Simulator is a large project written in C++ and utilizing Qt to build its Gui. There are large chunks of code that really have little to do with each other, such as the Navigator and Recorder modules, though even these two share some common menu functions. There is the potential for plug-ins that users can develop, that have to play nicely with the base code. Of course basically the code is held in files, usually containing just one class with related non-member functions, though occasionally a single file contains a few related classes, such as a base class and its derivatives. Related classes are grouped together in directories, and each directory is compiled together into a shared library. Among other things, grouping into libraries improves compilation time, because only libraries with changes need to be recompiled. All the libraries together with main.cpp comprise the program.

This represents the physical organization of the program, and was tough enough to figure out (and probably will change). Logically, there are classes and related non-member functions. These belong together, at least in the same header, because of Koenig lookup. Google that if you don’t know what it is. There are also some global typedefs, enums and functions outside of any class. They seem naked out there in global namespace, ready to conflict with some identically named function outside my control in a library somewhere. Surely they should be wrapped up in a namespace? Namespaces are the logical analogue to the physical library module. They can extend across files, or one file can have several namespaces. They can also be nested. Referring to something in another namespace requires prefixing the something with the namespace name, or using directives or declarations. The exact details are relatively simple, there are only a few rules to remember about how to use namespaces. When to use them is much harder, and there is precious little available as a guide.

I started out just wanting to wrap the global functions and enums and typedefs in a namespace. But what about my classes? Oh my gosh, they are also sitting out naked in the global namespace. Don’t they deserve a covering too?

I looked to see how my beautiful Gui-library, Qt, handled all this. All its classes were out in the global namespace too, their saving grace being that each begins with a capital Q, e.g. QListView. Qt defines only one namespace, the appropriately name Qt namespace, in which there are a bunch of enums. Somewhere on the net I found a statement that the Q thing was for historical reasons, so as not to break code, and that if they had their druthers, namespaces would be the norm in Qt. I next looked at KDE. They’ve got all their classes beginning with K, e.g. KApplication, but in addition there is a sprinkling of various namespaces, such as KDE — KDE::KApplication anyone? Of course my classes don’t begin with any particular letter and are just waiting to be gobbled up by outside libraries, except the only other library I’m using so far is the ubiquitous C++ standard library, where everything is in the std namespace. So no risk there.

But what about ADL, or Koenig lookup? Won’t things like non-member << operators fail if they are not in the same namespace (and I don’t mean the global namespace) as the class they relate to? Apparently not. Reading between lots of lines, Koenig lookup will work if the nonmember functions are in the same translation unit (i.e. header file, for all practical purposes) as the class they relate to. So no enclosing namespace is really necessary. I’ve also found that if I wrap everything in a namespace, it is hard to use items from that namespace in a class definition. You don’t want to use a using directive or declaration before the class definition, because, as classes are defined in header files, anyone who includes that header file will also import all the stuff from that namespace, wanted or not. And you can’t limit the scope of the using directive/declaration by have a using statement inside the class definition, because using in the class definition can never refer to a namespace, only to a base class!! For example:


namespace X {
int Y;
}


class Z {
using X::Y; // won't work!!
};

So, I’m still thinking about how best to use namespaces in a big application.



By mannd

I am a retired cardiac electrophysiologist who has worked both in private practice in Louisville, Kentucky and as a Professor of Medicine at the University of Colorado in Denver. I am interested not only in medicine, but also in computer programming, music, science fiction, fantasy, 30s pulp literature, and a whole lot more.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.