Thursday, August 29, 2013

wxWidgets and C++ 11

I've recently learnt that the latest edition of Bjarne Stroustrup's "The C++ Programming Language", updated to cover C++11, mentions wxWidgets as one of the commonly used C++ libraries (you can search the book at Amazon for "wxWidgets" to find the relevant paragraph). Being mentioned in the bible of C++ is always nice, of course, but isn't it strange that a book about C++11 references a purely C++98 library? Of course, C++11 is almost fully backwards compatible with C++98 and wxWidgets can be compiled with a C++11 compiler (e.g. under Unix, just pass CXX="g++ -std=c++11" to configure) but this is not very interesting. More so is how the new C++11 features make writing code using wxWidgets simpler and this is the topic of this post.

To illustrate this, let's look at a very simple program written in C++ 98: It simply shows a window with a button and increases the button font when it is pressed. It's not especially useful but does show a few typical constructs appearing in real-life programs. This version can be compiled with just about any C++ compiler (VC6 need not apply) and works with any wxWidgets version since 2.9.0, which introduced Bind().

So let's now look at the version updated to use some C++ 11 features: This version requires a C++11 compiler, e.g. g++ 4.7 or later (tested with 4.8), MSVC11 (a.k.a. Microsoft Visual Studio 2012) or clang 3. It also doesn't quite compile with wxWidgets 2.9.5, so currently you need the latest Git/SVN sources. But it will compile out of the box with wxWidgets 3.0, of course.

The functionality is exactly the same, so what are the differences?

  1. The most important change is undoubtedly the possibility to use lambdas as argument to Bind(). This is very useful for writing simple and short event handlers as it allows to keep the handler code together with the code creating (or loading from resources) the control. Notice that you need to capture this pointer by value in the lambda, hence the = in the line 12. Also notice that the lambda still must take (unused) wxCommandEvent&. This is something that we might get rid of in the future.
  2. The possibility to use the new for loop is also quite appreciable, notice how much simpler iterating over the child windows has become.
  3. Finally, there are small changes such as using nullptr instead of NULL, the added override in line 28 ensuring that you really override the base class method and using auto for the variables declaration. This is not really related to wxWidgets and I'm not completely convinced myself about the benefits of using auto everywhere (yet?) but if you are, perhaps after reading this article, you shouldn't encounter any problems doing it.

So, finally, even without any serious modifications to wxWidgets itself, the most user-visible changes of C++11 can be used in the programs using the library. Of course, there are many other C++11 features which would be very useful in the library implementation too and I'm very much looking forward to the variadic templates support becoming common enough to use them instead of the macro-based approach for the implementation of wxPrintf() and similar functions. But for now just using lambdas for the event handlers is already very nice.



Thanks to Herb Thompson for noticing this.

No comments: