Abandonment of wxCatalogue

25 April 2021
I have only one major C++ program to my name and today I formally abandoned it, and the program in question is wxCatalogue which is a utility I wrote out of the frustration of keeping track of all the electronic components I was buying in at the time. The tool has a history of its own, but the focus of this article is my view of C++ as a practial language — a view that has always been love-hate and with this it has moved much towards the latter.

Context

The first version of wxCatalogue was the penultimate program I wrote in Python 2 (the last being wxLED) and my motives for writing it have already been given in detail. Later on I rewrote it in C++ taking account of both better knowledge of wxPython/wxWidgets and of how I used the tool in practice, but as a result of irritations with the wxDataView GUI control it was built around I then did a second rewrite using GTK — while I did submit fixes to wxWidgets that would have got around these irritations, by that point I had decided to simply focus on the GTK rewrite that I had decided to call Leictreonach. Having got the latter to do what I want I simply could not justify listing the predecessor project as active.

Looking back at C++

Overall wxWidgets is very much a classic C++ tool-kit that I think is a good balance for someone like myself who is essentially a C developer, and for GUI development itself I think it is a good eco-system. The problem is that user interface development is one of those things where you really need more of the higher-level data manipulation functionality rather than access to low-level bits and bytes, and C++ makes a big mess of trying to cove both bases. I am always asking myself which is actually more painful: Contending with C++'s idiosyncrasies or the extra work of doing it all manually in C.

I/O streams

Coming from a C background C++'s I/O streams are an utter pain, with the iomanip interface being both very verbose and I am not even sure if it has the same level of flexibility as printf-style formatting. In practice wxWidgets own wxString class actually has a printf-like function and I think other C++ toolkits such as Boost do as well, and from what I have read C++20 finally added a format function but it may well be years before C++20 becomes universal and it seems to be modelled after Python's format rather than printf. So straight off the bat the availability of something that in C is the most basic function, in C++ is a question of both what revision the compiler actually supports and which toolkits are assumed to always be available. I stopped listing C++ on my CV because of the number of times companies were looking for a specific eco-system, which resulted in interviews that were more about trivia than measuring actual ability.

Iterators

Some parts of the standard template library such as std::list and std::map are very useful but the syntax for using them is pretty idiosyncratic, as demonstrated in the following snippet:

std::map<int,Entry*>::const_iterator iterItem; item = map.find( 42 ); if( item != map.end() ); { Entry *found = iterItem->second; // ...

Why the comparison with .end() and reading the found value through iterItem->second? Since the key is in iterItem->first I suspect this is down to the way C++ represents tuples. The verbose iterator signature of the iterator is a notable if understandable irritation, but other languages handle all this stuff a lot better. For instance in C++ iterating over a list is done using:

std::list<Something_t*>::iterator iter; for(iter = list.begin(); iter != list.end(); iter++) { Something_t *item = *iter; // ...

whereas in Python the equivalent is:

for item in list: # ...

Upshot of all of this is one of the few useful things that C++ bring to the table being a headache to use, to the extent that if I am using them a lot then I should consider a different language that implements them in a much more terse and friendly manner. At least in some cases I am simply better off writing my own support libraries rather than contending with these irritations.

Passing objects by value

I never really got to grips with how C++ does things with static allocation, such as the subtle differences that decide whether the copy constructor or the assignment operator gets called, in part because they are something that pretty much every other language out there does for you in the background. If I sat down I no doubt would find the actual concepts and all the pitfalls not that hard to understand, but a lot of the time I took the easy options of simply dynamically creating all my class instances because from my C background I know exactly how such pointers behave. Trouble is that by the time I am doing stuff like:

Node *node = new Node( .. ); node->doSomething( .. );

I am already pretty close to how I have always done things in C:

Node *node = nodeCreate( .. ); nodeDoSomething(node, .. );

Yes a little more discipline is needed to avoid name-space clashes but it saves me the need to deal with some of the more obscure C++ pitfalls coming along and ruining the show.

What about wxWidgets itself?

When I made the switch from wxPython to C++ wxWidgets the actual GUI control usage was not that different, save for a few minor irritations such as the wxVariant container, so i can foresee circumstances where I might have to opt for C++ & wxWidgets instead of wxPython Phoenix. In fact if I ever restart work on wxLED I may well port it to C++ because the program is basically entirely widget usage and is likely in need of an internal restructure anyway. On the whole I think wxWidgets is a lot better than GTK so I can foresee again using it for what would otherwise be a purely C-based program.

The real difficulty is actually the non-GUI stuff. With wxCatalogue the import filters remained as external Python-based tools for a lot longer than I wanted, as this is one of those things that Python is well suited for whereas C/C++ are actually quite painful. Even though I have both C and Python versions of Leictreonach the C version is just experimentation and I doubt it will supplant the Python version any time soon.

Conclusion

Every reason I have seen to use C++ instead of C is also a reason to use a higher-level language such as Python or Java, because the latter do a much better job of presenting higher-level functionality such as list operations. Using C++ as C with classes brings with it a lot of baggage that does not justify the convenience, so once again I am back to straight C programming.