c++-gtk-utils
gobj_handle.h
Go to the documentation of this file.
00001 /* Copyright (C) 2005 to 2011 Chris Vine
00002 
00003 The library comprised in this file or of which this file is part is
00004 distributed by Chris Vine under the GNU Lesser General Public
00005 License as follows:
00006 
00007    This library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public License
00009    as published by the Free Software Foundation; either version 2.1 of
00010    the License, or (at your option) any later version.
00011 
00012    This library is distributed in the hope that it will be useful, but
00013    WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License, version 2.1, for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License, version 2.1, along with this library (see the file LGPL.TXT
00019    which came with this source code package in the c++-gtk-utils
00020    sub-directory); if not, write to the Free Software Foundation, Inc.,
00021    59 Temple Place - Suite 330, Boston, MA, 02111-1307, USA.
00022 
00023 However, it is not intended that the object code of a program whose
00024 source code instantiates a template from this file or uses macros or
00025 inline functions (of any length) should by reason only of that
00026 instantiation or use be subject to the restrictions of use in the GNU
00027 Lesser General Public License.  With that in mind, the words "and
00028 macros, inline functions and instantiations of templates (of any
00029 length)" shall be treated as substituted for the words "and small
00030 macros and small inline functions (ten lines or less in length)" in
00031 the fourth paragraph of section 5 of that licence.  This does not
00032 affect any other reason why object code may be subject to the
00033 restrictions in that licence (nor for the avoidance of doubt does it
00034 affect the application of section 2 of that licence to modifications
00035 of the source code in this file).
00036 
00037 */
00038 
00039 #ifndef CGU_GOBJ_HANDLE_H
00040 #define CGU_GOBJ_HANDLE_H
00041 
00042 #include <exception>
00043 #include <functional> // for std::less and std::hash<T*>
00044 #include <cstddef>    // for std::size_t
00045 
00046 #include <glib-object.h>
00047 
00048 #include <c++-gtk-utils/cgu_config.h>
00049 
00050 /**
00051  * @addtogroup handles handles and smart pointers
00052  */
00053 
00054 namespace Cgu {
00055 
00056 /**
00057  * @class GobjHandle gobj_handle.h c++-gtk-utils/gobj_handle.h
00058  * @brief This is a handle for managing the reference count of
00059  * GObjects.
00060  * @ingroup handles
00061  * @sa MainWidgetBase GobjWeakHandle
00062  *
00063  * This is a class which manages the reference count of GObjects.  It
00064  * does not maintain its own reference count, but interfaces with that
00065  * kept by the glib object system.
00066  *
00067  * GobjHandles are most useful to manage GObjects which are not also
00068  * GtkWidgets or GInitiallyUnowned objects - GtkWidgets and
00069  * GInitiallyUnowned objects have initial floating references which
00070  * will result in them being automatically managed by the container in
00071  * which they are held.  Nonetheless, GobjHandles can be used to hold
00072  * GtkWidgets and GInitiallyUnowned objects, as the constructor of a
00073  * GobjHandle which takes a pointer will automatically take ownership
00074  * of a newly created GtkWidget or GInitiallyUnowned object, by
00075  * calling g_object_ref_sink().  Plain GObjects do not need to be sunk
00076  * to be owned by the GobjHandle.
00077  *
00078  * Note that g_object_ref_sink() is not called by the constructor
00079  * taking a pointer if the floating reference has already been sunk,
00080  * so if that constructor is passed an object already owned by a GTK+
00081  * container it will be necessary to call g_object_ref() on it
00082  * explicitly.  This behaviour will ensure that the handle behaves the
00083  * same whether it is holding a plain GObject, or it is holding a
00084  * GInitiallyUnowned/GtkWidget object.  Generally however, where an
00085  * object is already owned by a container, the object should be passed
00086  * by another handle - ie by the copy constructor (or by the
00087  * assignment operator), as those always increment the reference count
00088  * automatically.
00089  *
00090  * In other words, invoke the constructor taking a pointer only with a
00091  * newly created object (whether a GObject, GInitiallyUnowned or
00092  * GtkWidget object), and everything else will take care of itself. In
00093  * this respect, GobjHandles work the same way as conventional shared
00094  * pointer implementations managing objects allocated on free store.
00095  * The same applies to the reset() method.  (Care is required however
00096  * if initializing a Cgu::GobjHandle with a widget or GObject object
00097  * obtained from GtkBuilder, since these are not "newly created" in
00098  * this sense.  It is necessary to call g_object_ref() by hand in that
00099  * case, since GtkBuilder does not by itself pass ownership of any
00100  * objects it creates.)
00101  *
00102  * Because any GTK+ containers themselves increment the reference
00103  * count of a GObject or GtkWidget where they need to take ownership,
00104  * an already-managed object held by a GobjHandle can safely be passed
00105  * by pointer to a GTK+ container, and that is one of the intended
00106  * usages.  For that purpose, although the class has operator*() and
00107  * operator->() dereferencing operators, and so has normal smart
00108  * pointer functionality, as it is intended for use with the normal C
00109  * GObject/pango/GTK+ interfaces, ordinary use would involve passing
00110  * the handle to a function taking a pointer by means of the
00111  * operatorT*() type conversion operator (which returns the underlying
00112  * pointer), or by explicitly calling the get() method to obtain the
00113  * underlying pointer.
00114  *
00115  * The principal intended usage of GobjHandle is to automatically
00116  * handle GObject reference counts and therefore to make GObjects
00117  * exception-safe, but they also permit GObjects/GtkWidgets to be kept
00118  * in standard C++ containers.
00119  *
00120  * As of glib-2.8, g_object_ref() and g_object_unref() are thread
00121  * safe, so with glib-2.8 or greater there can be different GobjHandle
00122  * instances in different threads referencing the same GObject object.
00123  * Of course, if that is done, this does not affect the need (or
00124  * otherwise) in the particular use in question to lock anything other
00125  * than the reference count - say when accessing the referenced object
00126  * itself in different threads.
00127  *
00128  * Typical usage might be, for example, as follows:
00129  *
00130  * @code
00131  *   using namespace Cgu;
00132  *   GobjHandle<GtkListStore> store(gtk_list_store_new(1, G_TYPE_STRING));
00133  *
00134  *   [ ... fill the list store ... ]
00135  *
00136  *   GobjHandle<GtkWidget> view(gtk_tree_view_new_with_model(GTK_TREE_MODEL(store.get()));
00137  *   // 'view' will take sole ownership of the list store when 'store' goes out of scope, or
00138  *   // 'store' could be kept alive so that the list store will survive removal from the view
00139  *
00140  *   [ ... set up an interface including a GtkVBox 'vbox' which will hold the tree view ... ]
00141  *
00142  *   gtk_container_add(GTK_CONTAINER(vbox), view);
00143  *   // 'vbox' will take sole ownership of the tree view when 'view' goes out of scope, or
00144  *   // 'view' could be kept alive so that the tree view will survive removal from the vbox
00145  * @endcode
00146  */
00147 
00148 template <class T> class GobjHandle {
00149 
00150   T* obj_p;
00151 
00152   void unreference() {
00153     if (obj_p) g_object_unref(G_OBJECT(obj_p));
00154   }
00155 
00156   void reference() {
00157     if (obj_p) g_object_ref(G_OBJECT(obj_p));
00158   }
00159 
00160 public:
00161 
00162  /**
00163   * The constructor does not throw.  g_object_ref_sink() is called if
00164   * the managed object has a floating reference.
00165   * @param ptr The object which the GobjHandle is to manage (if any).
00166   * @note The object passed should not normally be already owned by a
00167   * GTK+ container or managed by any other GobjHandle object.  If it
00168   * is, g_object_ref() must be called explicitly by the user code.
00169   */
00170   explicit GobjHandle(T* ptr = 0) {
00171     obj_p = ptr;
00172 
00173     // if an object with a floating reference has been passed to this constructor,
00174     // take ownership of it
00175     if (ptr && g_object_is_floating(G_OBJECT(ptr))) {
00176       g_object_ref_sink(G_OBJECT(ptr));
00177     }
00178   }
00179 
00180  /**
00181   * Causes the handle to cease to manage its managed object (if any)
00182   * and decrements its reference count, so destroying it if the
00183   * reference count thereby becomes 0.  If the argument passed is not
00184   * NULL, the handle will manage the new object passed and
00185   * g_object_ref_sink() is called if the new object has a floating
00186   * reference.  This method does not throw.
00187   * @param ptr NULL (the default), or a new object to manage.
00188   * @note The new object passed should not normally be already owned
00189   * by a GTK+ container or managed by any other GobjHandle object.  If
00190   * it is, g_object_ref() must be called explicitly by the user code.
00191   */
00192   void reset(T* ptr = 0) {
00193     
00194     unreference();
00195     obj_p = ptr;
00196 
00197     // if an object with a floating reference has been passed to this method,
00198     // take ownership of it
00199     if (ptr && g_object_is_floating(G_OBJECT(ptr))) {
00200       g_object_ref_sink(G_OBJECT(ptr));
00201     }
00202   }
00203 
00204  /**
00205   * The copy constructor does not throw.  It increments the reference
00206   * count of the managed object.
00207   * @param gobj The handle to be copied.
00208   */
00209   GobjHandle(const GobjHandle& gobj) {
00210     obj_p = gobj.obj_p;
00211     reference();
00212   }
00213 
00214  /**
00215   * The move constructor does not throw.  It has move semantics.
00216   * @param gobj The handle to be moved.
00217   */
00218   GobjHandle(GobjHandle&& gobj) {
00219     obj_p = gobj.obj_p;
00220     gobj.obj_p = 0;
00221   }
00222 
00223   // We don't have a constructor for GobjHandle taking a GobjWeakHandle
00224   // object. If we did that, we would have to remove the GobjWeakHandle
00225   // constructor taking a pointer so we know that its tracked object
00226   // always has an owner when initialising a new GobjHandle with the
00227   // GobjWeakHandle, so we can in turn know we can increase the reference
00228   // count when initialising the GobjHandle.  However, removing that
00229   // constructor would be inconsistent with one of the purposes of having
00230   // a GobjWeakHandle class. For the same reason, we don't have an
00231   // assignment operator for GobjHandle taking such an object.
00232  /**
00233   * This method does not throw.  It decrements the reference count of
00234   * the former managed object (if any), so destroying it if the
00235   * reference count thereby becomes 0, and increments the reference
00236   * count of the new managed object.
00237   * @param gobj The assignor.
00238   * @return The GobjHandle object after assignment.
00239   */
00240   GobjHandle& operator=(const GobjHandle& gobj) {
00241 
00242     // check whether we are already referencing this object -
00243     // if so make this a null op.  This will also deal with
00244     // self-assignment
00245     if (obj_p != gobj.obj_p) {
00246 
00247       // first unreference any object referenced by this handle
00248       unreference();
00249 
00250       // now inherit the GObject from the assigning handle
00251       // and reference it
00252       obj_p = gobj.obj_p;
00253       reference();
00254     }
00255     return *this;
00256   }
00257 
00258  /**
00259   * This method does not throw.  It decrements the reference count of
00260   * the former managed object (if any), so destroying it if the
00261   * reference count thereby becomes 0, and has move semantics with
00262   * respect to the new managed object.
00263   * @param gobj The handle to be moved.
00264   * @return The GobjHandle object after the move operation.
00265   */
00266   GobjHandle& operator=(GobjHandle&& gobj) {
00267 
00268     // check for self-assignment
00269     if (this != &gobj) {
00270 
00271       // first unreference any object referenced by this handle
00272       unreference();
00273 
00274       // now inherit the GObject from the moving handle
00275       obj_p = gobj.obj_p;
00276       gobj.obj_p = 0;
00277     }
00278     return *this;
00279   }
00280 
00281  /**
00282   * This method does not throw.
00283   * @return A pointer to the handled GObject (or NULL if none is
00284   * handled).
00285   */
00286   T* get() const {return obj_p;}
00287 
00288  /**
00289   * This method does not throw.
00290   * @return A reference to the handled GObject.
00291   */
00292   T& operator*() const {return *obj_p;}
00293 
00294  /**
00295   * This method does not throw.
00296   * @return A pointer to the handled GObject (or NULL if none is
00297   * handled).
00298   */
00299   T* operator->() const {return obj_p;}
00300 
00301  /**
00302   * This method does not throw.
00303   * @return A pointer to the handled GObject (or NULL if none is
00304   * handled).
00305   */
00306   operator T*() const {return obj_p;}
00307 
00308  /**
00309   * The destructor does not throw.  It decrements the reference count
00310   * of the managed object (if any), so destroying it if the reference
00311   * count thereby becomes 0.
00312   */
00313   ~GobjHandle() {unreference();}
00314 };
00315 
00316 /**
00317  * @class GobjWeakHandle gobj_handle.h c++-gtk-utils/gobj_handle.h
00318  * @brief This is a handle for managing weak references to GObjects.
00319  * @ingroup handles
00320  * @sa GobjHandle
00321  *
00322  * This class tracks a GObject, so that if that GObject no longer
00323  * exists then operator bool() or the expired() method will return
00324  * false, but does not take a strong reference by incrementing the
00325  * reference count to the GObject and so take ownership of it.  It has
00326  * two main use areas: first, in order to break reference cycles that
00327  * may otherwise arise if two classes would otherwise hold strong
00328  * references to each other.  Secondly, to manage a pointer to a
00329  * GObject returned by a GTK+ getter function where ownership is not
00330  * passed (that is, where the user is not expected to call
00331  * g_object_unref() when finished with the return value).  A typical
00332  * example of this is the GtkTreeSelection object returned by
00333  * gtk_tree_view_get_selection().  The GtkTreeSelection object is part
00334  * of the GtkTreeView's implemention and will become invalid as soon
00335  * as the GtkTreeView object is finalized.
00336  *
00337  * As in the case of the GobjHandle class, although this class has
00338  * operator*() and operator->() dereferencing operators, and so has
00339  * normal smart pointer functionality, as it is intended for use with
00340  * the normal C GObject/pango/GTK+ interfaces, ordinary use would
00341  * involve passing the handle to a function taking a pointer by means
00342  * of the operatorT*() type conversion operator (which returns the
00343  * underlying pointer), or by explicitly calling the get() method to
00344  * obtain the underlying pointer.
00345  *
00346  * Typical usage is as follows:
00347  *
00348  * @code
00349  *   using namespace Cgu;
00350  *   GobjWeakHandle<GtkTreeSelection> s(gtk_tree_view_get_selection(tree_view));
00351  *   gtk_tree_selection_set_mode(s, GTK_SELECTION_SINGLE);
00352  *   ...
00353  *
00354  *   [some code blocks later]
00355  *   if (s) { // check that the GtkTreeSelection object still exists.
00356  *     GtkTreeIter iter;
00357  *     GtkTreeModel* model = 0;
00358  *     gtk_tree_selection_get_selected(s, &model, &iter);
00359  *     ...
00360  *   }
00361  *   else [report error];
00362  * @endcode
00363  *
00364  * Or instead of an 'if' block, GobjWeakHandleError could be caught:
00365  *
00366  * @code
00367  *   using namespace Cgu;
00368  *   GobjWeakHandle<GtkTreeSelection> s(gtk_tree_view_get_selection(tree_view));
00369  *   gtk_tree_selection_set_mode(s, GTK_SELECTION_SINGLE);
00370  *   ...
00371  *
00372  *   [some code blocks later]
00373  *   GtkTreeIter iter;
00374  *   GtkTreeModel* model = 0;
00375  *   try {
00376  *     gtk_tree_selection_get_selected(s, &model, &iter);
00377  *     ...
00378  *   }
00379  *   catch (GobjWeakHandleError&) {[report error]}
00380  * @endcode
00381  *
00382  * @b Thread-safe @b use
00383  *
00384  * This class wraps
00385  * g_object_add_weak_pointer()/g_object_remove_weak_pointer(), and as
00386  * those GObject functions have practical limitations concerning
00387  * thread-safe use, this class has the same practical limitations.  As
00388  * shown above, typical usage for a weak pointer 's' would be 'if (s)
00389  * do_it(s)', but if the thread calling that sequence (thread A) were
00390  * not the thread controlling the lifetime of the referenced GObject
00391  * (thread B), then thread B may have destroyed the GObject between
00392  * thread A testing 's' and then calling the referenced object.  The
00393  * same applies to the test leading to GobjWeakHandleError being
00394  * thrown.
00395  *
00396  * In other words, in the GtkTreeSelection code example above, if the
00397  * thread calling gtk_tree_selection_get_selected() were not the main
00398  * GUI thread (which would anyway require the use of
00399  * gdk_threads_enter()/gdk_threads_leave()), then the calling thread
00400  * must ensure that the main GUI thread does not destroy the relevant
00401  * tree view, and so the GtkTreeSelection object, from the beginning
00402  * of the 'if' test to the end of the 'if' block, or for the duration
00403  * of the try block.  (This cannot be done just by incrementing the
00404  * reference count of the tree view or the tree selection in the
00405  * calling thread before the 'if' test or the try block is entered,
00406  * because by the time the reference is incremented and the weak
00407  * pointer tested, the tree view and tree selection may already be in
00408  * their dispose functions but the tree selection's dispose function
00409  * may not yet have reached the point of dispatching the callback
00410  * NULLing the weak pointer.  As a general design issue, it is usually
00411  * best only to call GTK+ functions in one thread, and in order to
00412  * make that straightforward, this library contains a number of
00413  * classes and functions for inter-thread communication.)
00414  */
00415 
00416 struct GobjWeakHandleError: public std::exception {
00417   virtual const char* what() const throw() {return "GobjWeakHandleError\n";}
00418 };
00419 
00420 template <class T> class GobjWeakHandle {
00421 
00422   T* obj_p;
00423 
00424 public:
00425 
00426  /**
00427   * This constructor does not throw.
00428   * @param ptr The object which the GobjWeakHandle is to track (if any).
00429   */
00430   explicit GobjWeakHandle(T* ptr = 0) {
00431     obj_p = ptr;
00432     if (ptr) g_object_add_weak_pointer(G_OBJECT(ptr),
00433                                        (void**)&obj_p);
00434   }
00435 
00436  /**
00437   * Causes the handle to cease to track its tracked object (if any).
00438   * If the argument passed is not NULL, the handle will track the new
00439   * object passed.  This method does not throw.
00440   * @param ptr NULL (the default), or a new object to track.
00441   */
00442   void reset(T* ptr = 0) {
00443     
00444     if (obj_p) g_object_remove_weak_pointer(G_OBJECT(obj_p),
00445                                             (void**)&obj_p);
00446     obj_p = ptr;
00447     if (ptr) g_object_add_weak_pointer(G_OBJECT(ptr),
00448                                        (void**)&obj_p);
00449   }
00450 
00451  /**
00452   * The copy constructor does not throw.  It constructs a new weak
00453   * pointer tracking the same GObject as that tracked by the existing
00454   * weak pointer.
00455   * @param gobj The handle to be copied.
00456   */
00457   GobjWeakHandle(const GobjWeakHandle& gobj) {
00458     obj_p = gobj.obj_p;
00459     if (obj_p) g_object_add_weak_pointer(G_OBJECT(obj_p),
00460                                          (void**)&obj_p);
00461   }
00462 
00463  /**
00464   * This constructor constructs a weak pointer for a GObject managed
00465   * by a GobjHandle handle.  It does not throw.
00466   * @param gobj The GobjHandle managing the GObject which the
00467   * GobjWeakHandle is to track.
00468   */
00469   GobjWeakHandle(const GobjHandle<T>& gobj) {
00470     obj_p = gobj.get();
00471     if (obj_p) g_object_add_weak_pointer(G_OBJECT(obj_p),
00472                                          (void**)&obj_p);
00473   }
00474 
00475  /**
00476   * This method does not throw.  It causes the handle to cease to
00477   * track its tracked object (if any), and begin tracking the same
00478   * GObject as that tracked by the assignor.  This method does not
00479   * throw.
00480   * @param gobj The assignor.
00481   * @return The GobjWeakHandle object after assignment.
00482   */
00483   GobjWeakHandle& operator=(const GobjWeakHandle& gobj) {
00484     // self assignment takes care of itself
00485     reset(gobj.obj_p);
00486     return *this;
00487   }
00488 
00489  /**
00490   * This method does not throw.  It causes the handle to cease to
00491   * track its tracked object (if any), and begin tracking the GObject
00492   * managed by the GobjHandle argument.  This method does not throw.
00493   * @param gobj The assignor GobjHandle.
00494   * @return The GobjWeakHandle object after assignment.
00495   */
00496   GobjWeakHandle& operator=(const GobjHandle<T>& gobj) {
00497     reset(gobj.get());
00498     return *this;
00499   }
00500 
00501  /**
00502   * This method does not throw.
00503   * @return True if the tracked GObject still exists, or false if it
00504   * does not or no GObject is being tracked.
00505   * @note The expired() method is a synonym for this method.
00506   */
00507   operator bool() const {return obj_p;}
00508 
00509  /**
00510   * This method does not throw.
00511   * @return True if the tracked GObject still exists, or false if it
00512   * does not or no GObject is being tracked.
00513   * @note operator bool() is a synonym for this method.
00514   */
00515   bool expired() const {return obj_p;}
00516 
00517  /**
00518   * This method does not throw.
00519   * @return A pointer to the tracked GObject.
00520   * @exception GobjWeakHandleError This method will throw
00521   * GobjWeakHandleError if the tracked object no longer exists or none
00522   * is being tracked.  There is no need to check for this exception if
00523   * the status of the tracked object has been established with
00524   * operator bool() or expired().
00525   */
00526   T* get() const {if (!obj_p) throw GobjWeakHandleError(); return obj_p;}
00527 
00528  /**
00529   * This method does not throw.
00530   * @return A reference to the tracked GObject.
00531   * @exception GobjWeakHandleError This method will throw
00532   * GobjWeakHandleError if the tracked object no longer exists or none
00533   * is being tracked.  There is no need to check for this exception if
00534   * the status of the tracked object has been established with
00535   * operator bool() or expired().
00536   */
00537   T& operator*() const {if (!obj_p) throw GobjWeakHandleError(); return *obj_p;}
00538 
00539  /**
00540   * This method does not throw.
00541   * @return A pointer to the tracked GObject.
00542   * @exception GobjWeakHandleError This method will throw
00543   * GobjWeakHandleError if the tracked object no longer exists or none
00544   * is being tracked.  There is no need to check for this exception if
00545   * the status of the tracked object has been established with
00546   * operator bool() or expired().
00547   */
00548   T* operator->() const {if (!obj_p) throw GobjWeakHandleError(); return obj_p;}
00549 
00550  /**
00551   * This method does not throw.
00552   * @return A pointer to the tracked GObject.
00553   * @exception GobjWeakHandleError This method will throw
00554   * GobjWeakHandleError if the tracked object no longer exists or none
00555   * is being tracked.  There is no need to check for this exception if
00556   * the status of the tracked object has been established with
00557   * operator bool() or expired().
00558   */
00559   operator T*() const {if (!obj_p) throw GobjWeakHandleError(); return obj_p;}
00560 
00561  /**
00562   * The destructor does not throw.
00563   */
00564   ~GobjWeakHandle() {if (obj_p) g_object_remove_weak_pointer(G_OBJECT(obj_p),
00565                                                              (void**)&obj_p);}
00566 };
00567 
00568 #if defined(CGU_USE_SMART_PTR_COMPARISON) || defined(DOXYGEN_PARSING)
00569 
00570 // we can use built-in operator == when comparing pointers referencing
00571 // different objects of the same type
00572 /**
00573  * @ingroup handles
00574  *
00575  * This comparison operator does not throw.  It compares the addresses
00576  * of the managed objects.
00577  *
00578  * Since 2.0.0-rc2
00579  */
00580 template <class T>
00581 bool operator==(const GobjHandle<T>& h1, const GobjHandle<T>& h2) {
00582   return (h1.get() == h2.get());
00583 }
00584 
00585 /**
00586  * @ingroup handles
00587  *
00588  * This comparison operator does not throw.  It compares the addresses
00589  * of the managed objects.
00590  *
00591  * Since 2.0.0-rc2
00592  */
00593 template <class T>
00594 bool operator!=(const GobjHandle<T>& h1, const GobjHandle<T>& h2) {
00595   return !(h1 == h2);
00596 }
00597 
00598 // we must use std::less rather than the < built-in operator for
00599 // pointers to objects not within the same array or object: "For
00600 // templates greater, less, greater_equal, and less_equal, the
00601 // specializations for any pointer type yield a total order, even if
00602 // the built-in operators <, >, <=, >= do not." (para 20.3.3/8).
00603 /**
00604  * @ingroup handles
00605  *
00606  * This comparison operator does not throw.  It compares the addresses
00607  * of the managed objects.
00608  *
00609  * Since 2.0.0-rc2
00610  */
00611 template <class T>
00612 bool operator<(const GobjHandle<T>& h1, const GobjHandle<T>& h2) {
00613   return std::less<T*>()(h1.get(), h2.get());
00614 }
00615 
00616 #endif // CGU_USE_SMART_PTR_COMPARISON
00617 
00618 } // namespace Cgu
00619 
00620 // doxygen produces long filenames that tar can't handle:
00621 // we have generic documentation for std::hash specialisations
00622 // in doxygen.main.in
00623 #if defined(CGU_USE_SMART_PTR_COMPARISON) && !defined(DOXYGEN_PARSING)
00624 /* This struct allows GobjHandle objects to be keys in unordered
00625    associative containers */
00626 namespace std {
00627 template <class T>
00628 struct hash<Cgu::GobjHandle<T>> {
00629   typedef std::size_t result_type;
00630   typedef Cgu::GobjHandle<T> argument_type;
00631   result_type operator()(const argument_type& h) const {
00632     // this is fine: std::hash structs do not normally contain data and
00633     // std::hash<T*> certainly won't, so we don't have overhead constructing
00634     // std::hash<T*> on the fly
00635     return std::hash<T*>()(h.get());
00636   }
00637 };
00638 } // namespace std
00639 #endif // CGU_USE_SMART_PTR_COMPARISON
00640 
00641 #endif