]> git.tdb.fi Git - libs/gl.git/blobdiff - source/bindable.h
Rewrite Bind as two different classes
[libs/gl.git] / source / bindable.h
index bde5e85a11752b3a95a07de5187ad174b3c4a50a..f534d7afd8e9788e412dd0d2ddd876eee0091c8e 100644 (file)
@@ -66,95 +66,93 @@ public:
 /**
 RAII class for binding things.  Binds the thing upon construction and unbinds
 it upon destruction.  If a null pointer is given, unbinds upon construction and
-does nothing upon destruction.  Optionally can restore the previous binding.
+does nothing upon destruction.
 */
 class Bind
 {
 private:
-       struct Base
-       {
-               virtual ~Base() { }
-       };
+       typedef void CleanupFunc();
+
+       CleanupFunc *cleanup;
 
+public:
        template<typename T>
-       struct Binder1: Base
-       {
-               const T *obj;
-
-               Binder1(const T *o):
-                       obj(o)
-               {
-                       if(obj)
-                               obj->bind();
-                       else
-                               T::unbind();
-               }
-
-               ~Binder1()
-               {
-                       if(obj)
-                               obj->unbind();
-               }
-       };
-
-       template<typename T, typename U>
-       struct Binder2: Base
+       Bind(T *o) { init(o); }
+
+       template<typename T>
+       Bind(const T *o) { init(o); }
+
+       template<typename T>
+       Bind(const T &o) { init(&o); }
+
+private:
+       template<typename T>
+       void init(const T *o)
        {
-               const T *obj;
-               const U *old;
-
-               Binder2(const T *o, const U *l):
-                       obj(o),
-                       old(l)
-               {
-                       if(obj)
-                               obj->bind();
-                       else
-                               T::unbind();
-               }
-
-               ~Binder2()
-               {
-                       if(old)
-                               old->bind();
-                       else if(obj)
-                               obj->unbind();
-               }
-       };
-
-       Base *binder;
+               cleanup = (o ? &unbind<T> : 0);
+               if(o)
+                       o->bind();
+               else
+                       T::unbind();
+       }
+
+public:
+       ~Bind()
+       { if(cleanup) cleanup(); }
+
+private:
+       template<typename T>
+       static void unbind()
+       { T::unbind(); }
+};
+
+
+/**
+Similar to Bind, but restores previous binding upon destruction.
+*/
+class BindRestore
+{
+private:
+       typedef void CleanupFunc(const void *);
+
+       const void *old;
+       CleanupFunc *cleanup;
 
 public:
        template<typename T>
-       Bind(const T &o, bool r = false):
-               binder(r ? create(&o, T::current()) : create(&o))
-       { }
+       BindRestore(T *o) { init(o); }
 
        template<typename T>
-       Bind(const T *o, bool r = false):
-               binder(r ? create(o, T::current()) : create(o))
-       { }
+       BindRestore(const T *o) { init(o); }
 
        template<typename T>
-       Bind(T *o, bool r = false):
-               binder(r ? create(o, T::current()) : create(o))
-       { }
+       BindRestore(const T &o) { init(&o); }
 
 private:
-       Bind(const Bind &);
-       Bind &operator=(const Bind &);
+       template<typename T>
+       void init(T *o)
+       {
+               old = T::current();
+               cleanup = (o!=old ? &restore<T> : 0);
+               if(o)
+                       o->bind();
+               else if(old)
+                       T::unbind();
+       }
 
 public:
-       ~Bind() { delete binder; }
+       ~BindRestore()
+       { if(cleanup) cleanup(old); }
 
 private:
        template<typename T>
-       Base *create(const T *o)
-       { return new Binder1<T>(o); }
-
-       template<typename T, typename U>
-       Base *create(const T *o, const U *l)
-       { return new Binder2<T, U>(o, l); }
+       static void restore(const void *o)
+       {
+               if(o)
+                       reinterpret_cast<const T *>(o)->bind();
+               else
+                       T::unbind();
+       }
 };
 
 } // namespace GL