Switching to C++11

All the *mm projects now require C++11. Current versions of g++ require you to use the –std=c++11 option for this, but the next version will probably use C++11 by default. We might have done this sooner if it had been clearer that g++ (and libstdc++) really really supported C++11 fully.

I had expected that switching to C++11 would require an ABI break, but that has not happened, so already-built applications will not be affected. But our API now requires C++11 so this is a minor API change that you will notice when rebuilding your application.

Some distros, such as Fedora, are breaking the libstdc++ ABI slightly and requiring a rebuild of all applications, but that would have happened even without the *mm projects moving to C++11. It looks like Ubuntu might be doing this too, so I am still considering taking advantage of a forced (not gtkmm’s fault) widespread ABI break to make some ABI-breaking changes in gtkmm.

C++11 with autotools

You can use C++11 in your autotools-based project by calling AX_CXX_COMPILE_STDCXX_11() in your configure.ac after copying that m4 macro into your source tree. For instance, I used AX_CXX_COMPILE_STDCXX_11() in glom. The *mm projects use the MM_AX_CXX_COMPILE_STDCXX_11() macro that we added to mm-common, to avoid copying the .m4 file into every project. You may use that in your application instead. For instance, we used MM_AX_CXX_COMPILE_STDCXX_11() in the gtkmm-documentation module.

C++11 features

So far, the use of C++11 in gtkmm doesn’t provide much benefit to application developers and you can already use C++11 in applications that use older versions of gtkmm. But it makes life nicer for the gtkmm developers themselves. I’m enjoying learning about the new C++11 features (particularly move constructors) and enjoying our discussions about how best to use them.

I’m reading and re-reading Scott Meyer’s Effective Modern C++ book. C++11’s rvalue references alone require great care and understanding.

For now, we’ve just made these changes to the **mm projects:

Using auto to simplify the code.

For instance,

auto builder = Gtk::Builder::create();

For instance, auto builder = Gtk::Builder::create(); Using range-based for-loops.

For instance,

for(const auto& row : model->children()) { … }

For instance, for(const auto& row : model->children()) { … } Using nullptr instead of 0 or (void*)0.

For instance,

Gtk::Widget* widget = nullptr;

For instance, Gtk::Widget* widget = nullptr; Using the override keyword when we override a virtual method.

For instance,

bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;

For instance, bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override; Using noexcept instead of throw().

For instance,

virtual ~Exception() noexcept;

For instance, virtual ~Exception() noexcept; Using “= delete” instead of private unimplemented copy constructors and operator=().

Using C++11 lambdas, instead of sigc::slots, for small callback methods.

See below.

libsigc++ with C+11

libsigc++ has also moved to C++11 and we are gradually trying to replace as much as possible of its internals with C++11. Although C++11 has std::function, there’s still no C++11 equivalent for libsigc++ signals and object tracking

You can use C++11 lambda functions with libsigc++. For instance, with glibmm/gtkmm signals:

button.signal_clicked().connect( [] () { std::cout << "clicked" << std::endl; } );

And now you don’t need the awkard SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE macro if the signal/slot returns a value. For instance:

m_tree_model_filter->set_visible_func( [this] (const Gtk::TreeModel::const_iterator& iter) -> bool { auto row = *iter; return row[m_columns.m_col_show]; } );

With C++14 that should be even nicer:

m_tree_model_filter->set_visible_func( [this] (auto iter) -> decltype(auto) { auto row = *iter; return row[m_columns.m_col_show]; } );

These -> return type declarations are necessary in these examples just because of the unusual intermediate type returned by row[].