///////////////////////////////////////////////////////////////////////////////
/**
- * Utility class that simply unref's its argument in the destructor.
+ * 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.
*/
-template <typename T> class SkAutoTUnref : SkNoncopyable {
+
+template <typename T> class SkAutoTUnrefBase : SkNoncopyable {
public:
- explicit SkAutoTUnref(T* obj = NULL) : fObj(obj) {}
- ~SkAutoTUnref() { SkSafeUnref(fObj); }
+ ~SkAutoTUnrefBase() { SkSafeUnref(fObj); }
T* get() const { return fObj; }
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:
void ref() const;
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) {}
+
/**
* 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().
*/
- BlockRef<T> *operator->() const {
- return static_cast<BlockRef<T>*>(fObj);
+ typedef typename SkAutoTUnrefBase<T>::template BlockRef<T> BlockRefT;
+
+ BlockRefT* operator->() const {
+ return static_cast<BlockRefT*>(this->fObj);
}
- operator T*() { return fObj; }
+};
-private:
- T* 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;
+
+ const BlockRefT* operator->() const {
+ return static_cast<const BlockRefT*>(this->fObj);
+ }
};
class SkAutoUnref : public SkAutoTUnref<SkRefCnt> {