G_STATIC_ASSERT cannot be used with inherited C++ member functions
Submitted by George Kiagiadakis
Link to original bug (#655580)
Description
This is a follow-up from https://bugzilla.gnome.org/show_bug.cgi?id=653266
Consider the following code:
class Base { protected: int foo() { return 0; } };
class Foo : public Base { public: Foo() { G_STATIC_ASSERT(sizeof(foo()) == sizeof(int)); } };
(Ok, this is a completely stupid check, I just did it for demo purposes)
The problem with this code is that it fails to compile with: test.cpp:16:2: error: cannot call member function ‘int Base::foo()’ without object
This happens because G_STATIC_ASSERT internally uses a struct, and this struct causes the member function lookup to fail (not exactly sure why, though). To make it work, one needs to qualify the member function call by calling it using the "this" pointer (this->foo()).
This is generally not a problem for direct uses of G_STATIC_ASSERT, but for indirect uses like the one I am doing in QtGStreamer:
In a function I am calling: GST_CAPS_REFCOUNT_VALUE(object<GstCaps>
())
where object<GstCaps>
() is a template function from a base class that returns a GstCaps pointer. This is a macro that expands to:
#define GST_CAPS_REFCOUNT_VALUE(caps)
(g_atomic_int_get (&(GST_CAPS(caps))->refcount))
and g_atomic_int_get in glib 2.29 expands to:
#define g_atomic_int_get(atomic)
(G_GNUC_EXTENSION ({
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint));
(void) (0 ? *(atomic) ^ *(atomic) : 0);
__sync_synchronize ();
(gint) *(atomic);
}))
...and the G_STATIC_ASSERT call there fails.
In glib 2.28 and earlier this was not a problem because g_atomic_int_get used to expand to:
define g_atomic_int_get(atomic) \
((void) sizeof (gchar [sizeof (*(atomic)) == sizeof (gint) ? 1 : -1]),
(g_atomic_int_get) ((volatile gint G_GNUC_MAY_ALIAS *) (volatile void *)
(atomic)))
which worked as expected.
I think that a solution would be to use an enum instead of a struct in G_STATIC_ASSERT, or even check if the compiler is C++ and supports C++0x and use static_assert() directly. You could see BOOST_STATIC_ASSERT for reference.
Version: 2.29.x