Const correct BlockRef in SkAutoTUnref.
authorbungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 30 Jul 2012 15:03:59 +0000 (15:03 +0000)
committerbungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 30 Jul 2012 15:03:59 +0000 (15:03 +0000)
https://codereview.appspot.com/6448066/

git-svn-id: http://skia.googlecode.com/svn/trunk@4829 2bbb7eff-a529-9590-31e7-b0007b416f81

include/core/SkRefCnt.h
include/core/SkTemplates.h

index eab3c46..32e41db 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "SkThread.h"
 #include "SkInstCnt.h"
+#include "SkTemplates.h"
 
 /** \class SkRefCnt
 
@@ -135,14 +136,12 @@ template <typename T> static inline void SkSafeUnref(T* obj) {
 ///////////////////////////////////////////////////////////////////////////////
 
 /**
- * SkAutoTUnref is a utility class that simply unref's its argument in the
- * destructor. For implementation detail reasons there is a base class, a
- * derived general class, and a const-specialized derived class.
+ *  Utility class that simply unref's its argument in the destructor.
  */
-
-template <typename T> class SkAutoTUnrefBase : SkNoncopyable {
+template <typename T> class SkAutoTUnref : SkNoncopyable {
 public:
-    ~SkAutoTUnrefBase() { SkSafeUnref(fObj); }
+    explicit SkAutoTUnref(T* obj = NULL) : fObj(obj) {}
+    ~SkAutoTUnref() { SkSafeUnref(fObj); }
 
     T* get() const { return fObj; }
 
@@ -163,11 +162,9 @@ public:
         return obj;
     }
 
-    operator T*() { return fObj; }
-
     /**
-     * BlockRef<B> is a type which inherits from B, cannot be created, and makes
-     * ref and unref private.
+     * BlockRef<B> is a type which inherits from B, cannot be created,
+     * and makes ref and unref private.
      */
     template<typename B> class BlockRef : public B {
     private:
@@ -176,17 +173,8 @@ public:
         void unref() const;
     };
 
-protected:
-    explicit SkAutoTUnrefBase(T* obj) : fObj(obj) {}
-    T*  fObj;
-
-private:
-    SkAutoTUnrefBase();
-};
-
-template <typename T> class SkAutoTUnref : public SkAutoTUnrefBase<T> {
-public:
-    explicit SkAutoTUnref(T* obj = NULL) : SkAutoTUnrefBase<T>(obj) {}
+    /** If T is const, the type returned from operator-> will also be const. */
+    typedef typename SkTConstType<BlockRef<T>, SkTIsConst<T>::value>::type BlockRefType;
 
     /**
      *  SkAutoTUnref assumes ownership of the ref. As a result, it is an error
@@ -194,27 +182,13 @@ public:
      *  SkAutoTUnref::operator-> returns BlockRef<T>*. This prevents use of
      *  skAutoTUnrefInstance->ref() and skAutoTUnrefInstance->unref().
      */
-    typedef typename SkAutoTUnrefBase<T>::template BlockRef<T> BlockRefT;
-
-    BlockRefT* operator->() const {
-        return static_cast<BlockRefT*>(this->fObj);
+    BlockRefType *operator->() const {
+        return static_cast<BlockRefType*>(fObj);
     }
-};
-
-template <typename T> class SkAutoTUnref<const T> : public SkAutoTUnrefBase<const T> {
-public:
-    explicit SkAutoTUnref(const T* obj = NULL) : SkAutoTUnrefBase<const T>(obj) {}
-    /**
-     *  SkAutoTUnref assumes ownership of the ref. As a result, it is an error
-     *  for the user to ref or unref through SkAutoTUnref. Therefore
-     *  SkAutoTUnref::operator-> returns BlockRef<T>*. This prevents use of
-     *  skAutoTUnrefInstance->ref() and skAutoTUnrefInstance->unref().
-     */
-    typedef typename SkAutoTUnrefBase<const T>::template BlockRef<T> BlockRefT;
+    operator T*() { return fObj; }
 
-    const BlockRefT* operator->() const {
-        return static_cast<const BlockRefT*>(this->fObj);
-    }
+private:
+    T*  fObj;
 };
 
 class SkAutoUnref : public SkAutoTUnref<SkRefCnt> {
index 03f0892..a21a95d 100644 (file)
     resource management.
 */
 
+/**
+ *  SkTIsConst<T>::value is true if the type T is const.
+ *  The type T is constrained not to be an array or reference type.
+ */
+template <typename T> struct SkTIsConst {
+    static T* t;
+    static uint16_t test(const volatile void*);
+    static uint32_t test(volatile void *);
+    static const bool value = (sizeof(uint16_t) == sizeof(test(t)));
+};
+
+///@{
+/** SkTConstType<T, CONST>::type will be 'const T' if CONST is true, 'T' otherwise. */
+template <typename T, bool CONST> struct SkTConstType {
+    typedef T type;
+};
+template <typename T> struct SkTConstType<T, true> {
+    typedef const T type;
+};
+///@}
+
 /** \class SkAutoTCallVProc
 
     Call a function when this goes out of scope. The template uses two