#include <cstdio>
#include <cstdlib>
#include <utility>
template <typename T>
struct default_delete {
void operator ()(T *ptr) {
delete ptr;
}
};
template <typename T, typename Deleter = default_delete<T>>
class unique_ptr {
public:
unique_ptr(T* resource = nullptr, Deleter deleter = Deleter{})
: resource{resource}, deleter{deleter} {}
unique_ptr(const unique_ptr&) = delete;
unique_ptr(unique_ptr&& other)
: resource{std::move(other.resource)},
deleter{std::move(other.deleter)} {}
unique_ptr& operator=(const unique_ptr&) = delete;
unique_ptr& operator=(unique_ptr&& other) {
using std::swap;
swap(other.resource, resource);
swap(other.deleter, deleter);
}
~unique_ptr() {
deleter(resource);
}
T* get() { return resource; }
const T* get() const { return resource; }
private:
T* resource;
Deleter deleter;
};
/**** example starts here ****/
// partial specialization for arrays of default_delete
template <typename T>
struct default_delete<T[]> {
void operator()(T arr[]) {
delete[] arr;
}
};
// partial specialization of uniqe_ptr for arrays
// (to avoid adding another pointer layer to the array)
template <typename T, typename Deleter>
class unique_ptr<T[], Deleter> {
public:
unique_ptr(T resource[] = nullptr, Deleter deleter = Deleter{})
: resource{resource}, deleter{deleter} {}
unique_ptr(const unique_ptr&) = delete;
unique_ptr(unique_ptr&& other)
: resource{std::move(other.resource)},
deleter{std::move(other.deleter)} {}
unique_ptr& operator=(const unique_ptr&) = delete;
unique_ptr& operator=(unique_ptr&& other) {
using std::swap;
swap(other.resource, resource);
swap(other.deleter, deleter);
}
~unique_ptr() {
deleter(resource);
}
T* get() { return resource; }
const T* get() const { return resource; }
private:
T* resource;
Deleter deleter;
};
int main() {
unique_ptr<int[]> arr_ptr(new int[5]); // uses the specialized version with
// correct deleter
}