// -*- c++ -*- #pragma once #include #include namespace std { // [C++11 20.6.12.1] template T* addressof(T& r) noexcept { return reinterpret_cast(&(char&)r); } // [C++11 20.7.1.1] Default deleters template struct default_delete { constexpr default_delete() noexcept = default; template ::value>::type> default_delete(const default_delete&) noexcept { } void operator()(T* ptr) const { delete ptr; } }; template struct default_delete { constexpr default_delete() noexcept = default; void operator()(T* ptr) const { delete[] ptr; } template void operator()(U*) const = delete; }; // Use empty base optimization if D is an empty class. However, D // might also be a function type, in which case we can't subclass. template struct __uptr_impl; template struct __uptr_impl : private D { P ptr_; __uptr_impl(P ptr, const D &d) noexcept : D(d), ptr_(ptr) { } __uptr_impl(P ptr, D &&d) noexcept : D(std::move(d)), ptr_(ptr) { } D &get_deleter() { return *this; } }; template struct __uptr_impl { D d_; P ptr_; __uptr_impl(P ptr, const D &d) noexcept : d_(d), ptr_(ptr) { } __uptr_impl(P ptr, D &&d) noexcept : d_(std::move(d)), ptr_(ptr) { } D &get_deleter() { return d_; } }; // [C++11 20.7.1.2] template > class unique_ptr { public: typedef T* pointer; // XXX Violates standard typedef T element_type; typedef D deleter_type; private: __uptr_impl::value> impl_; public: constexpr unique_ptr() noexcept : impl_(nullptr, D()) { } explicit unique_ptr(pointer p) noexcept : impl_(p, D()) { } unique_ptr(pointer p, typename conditional::value, D, const D&>::type d) noexcept : impl_(p, d) { } unique_ptr(pointer p, typename remove_reference::type&& d) noexcept : impl_(std::move(p), std::move(d)) { static_assert(!is_reference::value, "rvalue deleter bound to reference"); } unique_ptr(unique_ptr&& u) noexcept : impl_(u.release(), std::forward(u.get_deleter())) { } constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } template ::pointer, pointer>::value && !is_array::value && conditional::value, is_same, is_convertible >::type::value>::type> unique_ptr(unique_ptr&& u) noexcept : impl_(u.release(), std::forward(u.get_deleter())) { } ~unique_ptr() { if (get() != nullptr) get_deleter()(get()); } unique_ptr& operator=(unique_ptr&& u) noexcept { reset(u.release()); get_deleter() = std::forward(u.get_deleter()); return *this; } template ::pointer, pointer>::value && !is_array::value>::type> unique_ptr& operator=(unique_ptr&& u) noexcept { reset(u.release()); get_deleter() = std::forward(u.get_deleter()); return *this; } unique_ptr& operator=(nullptr_t) noexcept { reset(); return *this; } typename add_lvalue_reference::type operator*() const { return *get(); } pointer operator->() const noexcept { return get(); } pointer get() const noexcept { return impl_.ptr_; } deleter_type& get_deleter() noexcept { return impl_.get_deleter(); } const deleter_type& get_deleter() const noexcept { return impl_.get_deleter(); } explicit operator bool() const noexcept { return get() != nullptr; } pointer release() noexcept { pointer p = get(); impl_.ptr_ = pointer(); return p; } void reset(pointer p = pointer()) noexcept { pointer o = get(); impl_.ptr_ = p; if (o != pointer()) get_deleter()(o); } void swap(unique_ptr& u) noexcept { std::swap(impl_.ptr_, u.impl_.ptr_); std::swap(get_deleter(), u.get_deleter()); } // Disable copy from lvalue unique_ptr(const unique_ptr&) = delete; unique_ptr& operator=(const unique_ptr&) = delete; }; // [C++11 20.7.1.3] template class unique_ptr { public: typedef T* pointer; // XXX Violates standard typedef T element_type; typedef D deleter_type; private: __uptr_impl::value> impl_; public: constexpr unique_ptr() noexcept : impl_(nullptr, D()) { } explicit unique_ptr(pointer p) noexcept : impl_(p, D()) { } unique_ptr(pointer p, typename conditional::value, D, const D&>::type d) noexcept : impl_(p, d) { } unique_ptr(pointer p, typename remove_reference::type&& d) noexcept : impl_(std::move(p), std::move(d)) { static_assert(!is_reference::value, "rvalue deleter bound to reference"); } unique_ptr(unique_ptr&& u) noexcept : impl_(u.release(), std::forward(u.get_deleter())) { } constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } ~unique_ptr() { if (get() != nullptr) get_deleter()(get()); } unique_ptr& operator=(unique_ptr&& u) noexcept { reset(u.release()); get_deleter() = std::forward(u.get_deleter()); return *this; } unique_ptr& operator=(nullptr_t) noexcept { reset(); return *this; } T& operator[](size_t i) const { return get()[i]; } pointer get() const noexcept { return impl_.ptr_; } deleter_type& get_deleter() noexcept { return impl_.get_deleter(); } explicit operator bool() const noexcept { return get() != nullptr; } pointer release() noexcept { pointer p = get(); impl_.ptr_ = pointer(); return p; } void reset(pointer p = pointer()) noexcept { pointer o = get(); impl_.ptr_ = p; if (o != pointer()) get_deleter()(o); } // Disallow resetting to convertible pointer types template::value && is_convertible::value && is_base_of::value && !is_same::type, typename remove_cv::type>::value>::type> void reset(U*) = delete; void swap(unique_ptr& u) noexcept { std::swap(impl_.ptr_, u.impl_.ptr_); std::swap(get_deleter(), u.get_deleter()); } }; // [C++14 20.8.1.4] template struct __make_unique_result { typedef unique_ptr single; }; template struct __make_unique_result { typedef unique_ptr array; }; template struct __make_unique_result { struct invalid { }; }; template typename __make_unique_result::single make_unique(Args&& ...args) { return std::unique_ptr(new T(std::forward(args)...)); } template typename __make_unique_result::array make_unique(size_t bound) { return unique_ptr(new typename remove_extent::type[bound]()); } template typename __make_unique_result::invalid make_unique(Args&&...) = delete; }