GNOME Bugzilla – Bug 680994
STATIC_ASSERT in GDBusError docs don't have much utility
Last modified: 2012-08-03 11:38:13 UTC
From https://bugzilla.gnome.org/show_bug.cgi?id=678057#c95 http://developer.gnome.org/gio/unstable/gio-GDBusError.html#gio-GDBusError.description The G_STATIC_ASSERT checks if the last item in the enum is the last item in the mapping: enum { ONE, TWO, THREE, }; GDBusErrorEntry mapping[] = { { ONE, "one" }, { TWO, "two" }, { THREE, "three" }, }; G_STATIC_ASSERT (G_NUM_ELEMENTS (mapping), THREE - 1); This is clearly designed to prevent against new errors that are not in the mapping. But in the most common case, appending to the end of the enum, the static assert will not fire, as THREE hasn't shifted its place: enum { ONE, TWO, THREE, FOUR, }; GDBusErrorEntry mapping[] = { { ONE, "one" }, { TWO, "two" }, { THREE, "three" }, }; G_STATIC_ASSERT (G_NUM_ELEMENTS (mapping), THREE - 1);
How about this fix? * FOO_BAR_ERROR_FAILED, * FOO_BAR_ERROR_ANOTHER_ERROR, * FOO_BAR_ERROR_SOME_THIRD_ERROR, + * FOO_BAR_ERROR_N_ERRORS /*< skip *>/ * } FooBarError; * * /<!-- -->* foo-bar-error.c: *<!-- -->/ @@ -83,11 +84,11 @@ * foo_bar_error_quark (void) * { * static volatile gsize quark_volatile = 0; + * G_STATIC_ASSERT (G_N_ELEMENTS (foo_bar_error_entries) == FOO_BAR_ERROR_N_ERRORS); * g_dbus_error_register_error_domain ("foo-bar-error-quark", * &quark_volatile, * foo_bar_error_entries, * G_N_ELEMENTS (foo_bar_error_entries)); - * G_STATIC_ASSERT (G_N_ELEMENTS (foo_bar_error_entries) - 1 == FOO_BAR_ERROR_SOME_THIRD_ERROR); * return (GQuark) quark_volatile; * } * </programlisting></example>
After discussion on IRC, I ended up committing this fix http://git.gnome.org/browse/glib/commit/?id=800ca21e555e5e9fe1f07a4a8473d6d24ada6301
Note you typically want to use #define FOO_N_ELEMENTS FOO_LAST_ELEMENT instead of adding it to the enum itself; this helps avoid gcc warning you if it's missing from switch statements.
I agree with the logic on the define, but I really prefer the N_ to the LAST_...
(but I think the #define is only required if it's required.... which in this case it seems not to be.)