Last active
May 16, 2020 02:50
-
-
Save steipete/0f65c234ee843ed514ff to your computer and use it in GitHub Desktop.
A C++ smart pointer for CoreFoundation objects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// hpp: | |
/// A smart pointer that can manage the lifecycle of Core Foundation objects. | |
template<typename T> | |
class CFPointer { | |
public: | |
CFPointer() : storage(nullptr) { } | |
CFPointer(T pointer) : storage(toStorageType(pointer)) { | |
if (storage) { | |
CFRetain(storage); | |
} | |
} | |
CFPointer(const CFPointer & other) : storage(other.storage) { | |
if (CFTypeRef ptr = storage) { | |
CFRetain(ptr); | |
} | |
} | |
CFPointer(CFPointer && other) : storage(std::exchange(other.storage, nullptr)) { } | |
~CFPointer() { | |
if (CFTypeRef pointer = storage) { | |
CFRelease(pointer); | |
} | |
} | |
static inline CFPointer<T> adopt(T CF_RELEASES_ARGUMENT ptr); | |
T get() const; | |
CFPointer &operator=(CFPointer); | |
private: | |
CFTypeRef storage; | |
enum AdoptTag { Adopt }; | |
CFPointer(T ptr, AdoptTag) : storage(toStorageType(ptr)) { } | |
inline CFTypeRef toStorageType(CFTypeRef ptr) const { | |
return (CFTypeRef)ptr; | |
} | |
inline T fromStorageType(CFTypeRef pointer) const { | |
return (T)pointer; | |
} | |
void swap(CFPointer &); | |
}; | |
template<typename T> | |
CFPointer<T> CFPointer<T>::adopt(T CF_RELEASES_ARGUMENT ptr) { | |
return CFPointer<T>(ptr, CFPointer<T>::Adopt); | |
} | |
template<typename T> | |
T CFPointer<T>::get() const { | |
return fromStorageType(storage); | |
} | |
template<typename T> | |
inline CFPointer<T>& CFPointer<T>::operator=(CFPointer other) { | |
swap(other); | |
return *this; | |
} | |
template<typename T> | |
inline void CFPointer<T>::swap(CFPointer &other) { | |
std::swap(storage, other.storage); | |
} | |
// cpp: | |
/// A smart pointer that can manage the lifecycle of Core Foundation objects. | |
template<typename T> | |
class CFPointer { | |
public: | |
CFPointer() : storage(nullptr) { } | |
CFPointer(T pointer) : storage(toStorageType(pointer)) { | |
if (storage) { | |
CFRetain(storage); | |
} | |
} | |
CFPointer(const CFPointer & other) : storage(other.storage) { | |
if (CFTypeRef ptr = storage) { | |
CFRetain(ptr); | |
} | |
} | |
CFPointer(CFPointer && other) : storage(std::exchange(other.storage, nullptr)) { } | |
~CFPointer() { | |
if (CFTypeRef pointer = storage) { | |
CFRelease(pointer); | |
} | |
} | |
static inline CFPointer<T> adopt(T CF_RELEASES_ARGUMENT ptr); | |
T get() const; | |
CFPointer &operator=(CFPointer); | |
private: | |
CFTypeRef storage; | |
enum AdoptTag { Adopt }; | |
CFPointer(T ptr, AdoptTag) : storage(toStorageType(ptr)) { } | |
inline CFTypeRef toStorageType(CFTypeRef ptr) const { | |
return (CFTypeRef)ptr; | |
} | |
inline T fromStorageType(CFTypeRef pointer) const { | |
return (T)pointer; | |
} | |
void swap(CFPointer &); | |
}; | |
template<typename T> | |
CFPointer<T> CFPointer<T>::adopt(T CF_RELEASES_ARGUMENT ptr) { | |
return CFPointer<T>(ptr, CFPointer<T>::Adopt); | |
} | |
template<typename T> | |
T CFPointer<T>::get() const { | |
return fromStorageType(storage); | |
} | |
template<typename T> | |
inline CFPointer<T>& CFPointer<T>::operator=(CFPointer other) { | |
swap(other); | |
return *this; | |
} | |
template<typename T> | |
inline void CFPointer<T>::swap(CFPointer &other) { | |
std::swap(storage, other.storage); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@steipete, I just watched your AltConf lecture - thanks for the tips! Is there any specific reason you've re-implemented
unique_ptr
instead of just implementing a custom deleter (or a specialization of std::default_delete) that callsCFRelease
?