The issue is a side effect of Glib::RefPtr<T>:
- declaring operators == and !=
- declaring operator bool()
- not declaring operators <, <=, >, >=
The operators == and != compare pointers for equality and work as expected. The operator bool() is defined to allow the following usage of a RefPtr:
if (ref_ptr) puts("is non-null"); else puts("is null");
STL sorted containers need operator< on the type they contain. Assuming p1 and p2 are of type Glib::RefPtr<T>, the following compiles just fine:
p1 < p2
This in turn means that e.g. std::set<Glib::RefPtr<T> > my_map; compiles. Unfortunately, with current version of glibmm, this breaks badly at runtime.
Why? As there's no custom operator<, the compiler interprets p1 < p2 like this:
(bool)p1 < (bool)p2
This is true iff p1 is NULL and p2 is non-NULL. The operators <=, >, >= also work on the results of operator bool(). So, depending on the pointers wrapped in p1 and p2, it's possible that the following would be true:
p1 != p2 && !(p1 < p2) && !(p1 > p2)
(this is true iff p1 and p2 wrap two different non-NULL pointers)
There's a bug report for the issue.
A workaround for the time being is to use a custom comparator like this:
template<typename T> class RefPtrLess { public: bool operator() (const Glib::RefPtr<T> &a, const Glib::RefPtr<T> &b) { const T* const a_ptr = a.operator->(); const T* const b_ptr = b.operator->(); return a_ptr < b_ptr; } }; typedef std::set<Glib::RefPtr<MyType>, RefPtrLess<MyType> > TMyTypeSet;