aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/core
diff options
context:
space:
mode:
authorGravatar bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-07-30 15:03:59 +0000
committerGravatar bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-07-30 15:03:59 +0000
commit91208922687a33df1d5253928b8d5d7d4685c7ac (patch)
treee6249206a4d2fce588d13b9ecd343645e2a98afb /include/core
parent58be682c77c76d9a0caf23337f9b357798179b6c (diff)
Const correct BlockRef in SkAutoTUnref.
Diffstat (limited to 'include/core')
-rw-r--r--include/core/SkRefCnt.h54
-rw-r--r--include/core/SkTemplates.h21
2 files changed, 35 insertions, 40 deletions
diff --git a/include/core/SkRefCnt.h b/include/core/SkRefCnt.h
index eab3c46eb7..32e41dbd6a 100644
--- a/include/core/SkRefCnt.h
+++ b/include/core/SkRefCnt.h
@@ -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> {
diff --git a/include/core/SkTemplates.h b/include/core/SkTemplates.h
index 03f0892fac..a21a95d48b 100644
--- a/include/core/SkTemplates.h
+++ b/include/core/SkTemplates.h
@@ -18,6 +18,27 @@
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