Index: uspace/lib/cpp/include/impl/memory.hpp
===================================================================
--- uspace/lib/cpp/include/impl/memory.hpp	(revision 973a268b31c3de6009dbd02163597cc001450d43)
+++ uspace/lib/cpp/include/impl/memory.hpp	(revision 40340461bf1a7b428bec8eefc784626cf4312724)
@@ -428,4 +428,597 @@
         return first;
     }
+
+    /**
+     * 20.8, smart pointers:
+     */
+
+    template<class T>
+    struct default_delete
+    {
+        default_delete() noexcept = default;
+
+        template<class U, class = enable_if_t<is_convertible_v<U*, T*>, void>>
+        default_delete(const default_delete<U>&) noexcept
+        { /* DUMMY BODY */ }
+
+        template<class U>
+        void operator()(U* ptr)
+        {
+            delete ptr;
+        }
+    };
+
+    template<class T>
+    struct default_delete<T[]>
+    {
+        default_delete() noexcept = default;
+
+        template<class U, class = enable_if_t<is_convertible_v<U(*)[], T(*)[]>, void>>
+        default_delete(const default_delete<U[]>&) noexcept
+        { /* DUMMY BODY */ }
+
+        template<class U, class = enable_if_t<is_convertible_v<U(*)[], T(*)[]>, void>>
+        void operator()(U* ptr)
+        {
+            delete[] ptr;
+        }
+    };
+
+    template<class T, class D = default_delete<T>>
+    class unique_ptr;
+
+    namespace aux
+    {
+        template<class P, class D, class = void>
+        struct get_unique_pointer: type_is<typename P::element_type*>
+        { /* DUMMY BODY */ };
+
+        template<class P, class D>
+        struct get_unique_pointer<P, D, void_t<typename remove_reference_t<D>::pointer>>
+            : type_is<typename remove_reference_t<D>::pointer>
+        { /* DUMMY BODY */ };
+    }
+
+    template<class T, class D>
+    class unique_ptr
+    {
+        public:
+            using element_type = T;
+            using deleter_type = D;
+            using pointer      = typename aux::get_unique_pointer<unique_ptr<T, D>, D>::type;
+
+            /**
+             * 20.8.1.2.1, constructors:
+             */
+
+            constexpr unique_ptr() noexcept
+                : ptr_{}, deleter_{}
+            { /* DUMMY BODY */ }
+
+            explicit unique_ptr(pointer ptr) noexcept
+                : ptr_{ptr}, deleter_{}
+            { /* DUMMY BODY */ }
+
+            unique_ptr(pointer ptr, /* TODO */ int d) noexcept;
+
+            unique_ptr(pointer ptr, /* TODO */ char d) noexcept;
+
+            unique_ptr(unique_ptr&& other)
+                : ptr_{move(other.ptr_)}, deleter_{forward<deleter_type>(other.deleter_)}
+            {
+                other.ptr_ = nullptr;
+            }
+
+            constexpr unique_ptr(nullptr_t)
+                : unique_ptr{}
+            { /* DUMMY BODY */ }
+
+            template<
+                class U, class E,
+                class = enable_if_t<
+                    is_convertible_v<
+                        typename unique_ptr<U, E>::pointer,
+                        pointer
+                    >, void
+                >
+            >
+            unique_ptr(unique_ptr<U, E>&& other) noexcept
+                : ptr_{move(other.ptr_)}, deleter_{forward<D>(other.deleter_)}
+            {
+                other.ptr_ = nullptr;
+            }
+
+            /**
+             * 20.8.1.2.2, destructor:
+             */
+
+            ~unique_ptr()
+            {
+                if (ptr_)
+                    deleter_(ptr_);
+            }
+
+            /**
+             * 20.8.1.2.3, assignment:
+             */
+
+            unique_ptr& operator=(unique_ptr&& rhs) noexcept
+            {
+                reset(rhs.release());
+                deleter_ = forward<deleter_type>(rhs.get_deleter());
+
+                return *this;
+            }
+
+            template<
+                class U, class E,
+                class = enable_if_t<
+                    is_convertible_v<
+                        typename unique_ptr<U, E>::pointer,
+                        pointer
+                    > && !is_array_v<U>, void
+                >
+            >
+            unique_ptr& operator=(unique_ptr<U, E>&& rhs) noexcept
+            {
+                reset(rhs.release());
+                deleter_ = forward<E>(rhs.get_deleter());
+
+                return *this;
+            }
+
+            unique_ptr& operator=(nullptr_t) noexcept
+            {
+                reset();
+
+                return *this;
+            }
+
+            /**
+             * 20.8.1.2.4, observers:
+             */
+
+            add_lvalue_reference_t<element_type> operator*() const
+            {
+                return *ptr_;
+            }
+
+            pointer operator->() const noexcept
+            {
+                return ptr_;
+            }
+
+            pointer get() const noexcept
+            {
+                return ptr_;
+            }
+
+            deleter_type& get_deleter() noexcept
+            {
+                return deleter_;
+            }
+
+            const deleter_type& get_deleter() const noexcept
+            {
+                return deleter_;
+            }
+
+            explicit operator bool() const noexcept
+            {
+                return ptr_ != nullptr;
+            }
+
+            /**
+             * 20.8.1.2.5, modifiers:
+             */
+
+            pointer release() noexcept
+            {
+                auto ret = ptr_;
+                ptr_ = nullptr;
+
+                return ret;
+            }
+
+            void reset(pointer ptr = pointer{}) noexcept
+            {
+                /**
+                 * Note: Order is significant, deleter may delete
+                 *       *this.
+                 */
+                auto old = ptr_;
+                ptr_ = ptr;
+
+                if (old)
+                    deleter_(old);
+            }
+
+            void swap(unique_ptr& other) noexcept
+            {
+                std::swap(ptr_, other.ptr_);
+                std::swap(deleter_, other.deleter_);
+            }
+
+            unique_ptr(const unique_ptr&) = delete;
+            unique_ptr& operator=(const unique_ptr&) = delete;
+
+        private:
+            pointer ptr_;
+            deleter_type deleter_;
+    };
+
+    namespace aux
+    {
+        template<class From, class To>
+        struct is_convertible_array: is_convertible<From(*)[], To(*)[]>
+        { /* DUMMY BODY */ };
+
+        template<class From, class To>
+        inline constexpr bool is_convertible_array_v = is_convertible_array<From, To>::value;
+
+        template<class T, class D, class U, class E>
+        struct compatible_ptrs: integral_constant<
+              bool,
+              is_array_v<U> && is_same_v<
+                typename unique_ptr<T, D>::pointer,
+                typename unique_ptr<T, D>::element_type*
+              > && is_same_v<
+                typename unique_ptr<U, E>::pointer,
+                typename unique_ptr<U, E>::element_type*
+              > && is_convertible_array_v<
+                typename unique_ptr<T, D>::element_type,
+                typename unique_ptr<U, E>::element_type
+              > && ((is_reference_v<D> && is_same_v<D, E>) ||
+                   (!is_reference_v<D> && is_convertible_v<E, D>))
+        >
+        { /* DUMMY BODY */ };
+
+        template<class T, class D, class U, class E>
+        inline constexpr bool compatible_ptrs_v = compatible_ptrs<T, D, U, E>::value;
+    }
+
+    template<class T, class D>
+    class unique_ptr<T[], D>
+    {
+        public:
+            using element_type = T;
+            using deleter_type = D;
+            using pointer      = typename aux::get_unique_pointer<unique_ptr<T[], D>, D>::type;
+
+            /**
+             * 20.8.1.3.1, constructors:
+             */
+
+            constexpr unique_ptr() noexcept
+                : ptr_{}, deleter_{}
+            { /* DUMMY BODY */ }
+
+            template<
+                class U,
+                class = enable_if_t<
+                    is_same_v<U, T> || aux::is_convertible_array_v<U, T>, void
+                >
+            >
+            explicit unique_ptr(U ptr) noexcept
+                : ptr_{ptr}, deleter_{}
+            { /* DUMMY BODY */ }
+
+            template<
+                class U, class E,
+                class = enable_if_t<aux::compatible_ptrs_v<T, D, U, E>, void>
+            >
+            unique_ptr(U ptr, /* TODO */ int d) noexcept;
+
+            template<
+                class U, class E,
+                class = enable_if_t<aux::compatible_ptrs_v<T, D, U, E>, void>
+            >
+            unique_ptr(U ptr, /* TODO */ char d) noexcept;
+
+            unique_ptr(unique_ptr&& other) noexcept
+                : ptr_{move(other.ptr_)}, deleter_{forward<deleter_type>(other.deleter_)}
+            {
+                other.ptr_ = nullptr;
+            }
+
+            template<
+                class U, class E,
+                class = enable_if_t<
+                    is_same_v<U, pointer> ||
+                    (is_same_v<pointer, element_type*> && is_pointer_v<U> &&
+                     aux::is_convertible_array_v<remove_pointer_t<U>, element_type>),
+                    void
+                >
+            >
+            unique_ptr(unique_ptr<U, E>&& other) noexcept
+                : ptr_{move(other.ptr_)}, deleter_{forward<D>(other.deleter_)}
+            {
+                other.ptr_ = nullptr;
+            }
+
+            constexpr unique_ptr(nullptr_t) noexcept
+                : unique_ptr{}
+            { /* DUMMY BODY */ }
+
+            ~unique_ptr()
+            {
+                if (ptr_)
+                    deleter_(ptr_);
+            }
+
+            /**
+             * 20.8.1.3.2, assignment:
+             */
+
+            unique_ptr& operator=(unique_ptr&& rhs) noexcept
+            {
+                reset(rhs.release());
+                deleter_ = forward<deleter_type>(rhs.get_deleter());
+
+                return *this;
+            }
+
+            template<
+                class U, class E,
+                class = enable_if_t<aux::compatible_ptrs_v<T, D, U, E>, void>
+            >
+            unique_ptr& operator=(unique_ptr<U, E>&& rhs) noexcept
+            {
+                reset(rhs.release());
+                deleter_ = forward<E>(rhs.get_deleter());
+
+                return *this;
+            }
+
+            unique_ptr& operator=(nullptr_t) noexcept
+            {
+                reset();
+
+                return *this;
+            }
+
+            /**
+             * 20.8.1.3.3, observers:
+             */
+
+            element_type& operator[](size_t idx) const
+            {
+                return ptr_[idx];
+            }
+
+            pointer get() const noexcept
+            {
+                return ptr_;
+            }
+
+            deleter_type& get_deleter() noexcept
+            {
+                return deleter_;
+            }
+
+            const deleter_type& get_deleter() const noexcept
+            {
+                return deleter_;
+            }
+
+            explicit operator bool() const noexcept
+            {
+                return ptr_ != nullptr;
+            }
+
+            /**
+             * 20.8.1.3.4, modifiers:
+             */
+
+            pointer release() noexcept
+            {
+                auto ret = ptr_;
+                ptr_ = nullptr;
+
+                return ret;
+            }
+
+            template<
+                class U,
+                class = enable_if_t<
+                    is_same_v<U, pointer> ||
+                    (is_same_v<pointer, element_type*> && is_pointer_v<U> &&
+                     aux::is_convertible_array_v<remove_pointer_t<U>, element_type>),
+                    void
+                >
+            >
+            void reset(U ptr) noexcept
+            {
+                /**
+                 * Note: Order is significant, deleter may delete
+                 *       *this.
+                 */
+                auto old = ptr_;
+                ptr_ = ptr;
+
+                if (old)
+                    deleter_(old);
+            }
+
+            void reset(nullptr_t = nullptr) noexcept
+            {
+                reset(pointer{});
+            }
+
+            void swap(unique_ptr& other) noexcept
+            {
+                std::swap(ptr_, other.ptr_);
+                std::swap(deleter_, other.deleter_);
+            }
+
+            unique_ptr(const unique_ptr&) = delete;
+            unique_ptr& operator=(const unique_ptr&) = delete;
+
+        private:
+            pointer ptr_;
+            deleter_type deleter_;
+    };
+
+    namespace aux
+    {
+        template<class T>
+        struct is_unbound_array: false_type
+        { /* DUMMY BODY */ };
+
+        template<class T>
+        struct is_unbound_array<T[]>: true_type
+        { /* DUMMY BODY */ };
+
+        template<class T>
+        struct is_bound_array: false_type
+        { /* DUMMY BODY */ };
+
+        template<class T, size_t N>
+        struct is_bound_array<T[N]>: true_type
+        { /* DUMMY BODY */ };
+    }
+
+    template<
+        class T, class... Args,
+        class = enable_if_t<!is_array_v<T>, void>
+    >
+    unique_ptr<T> make_unique(Args&&... args)
+    {
+        return unique_ptr<T>(new T(forward<Args>(args)...));
+    }
+
+    template<
+        class T, class = enable_if_t<aux::is_unbound_array<T>::value, void>
+    >
+    unique_ptr<T> make_unique(size_t n)
+    {
+        return unique_ptr<T>(new remove_extent_t<T>[n]());
+    }
+
+    template<
+        class T, class... Args,
+        class = enable_if_t<aux::is_bound_array<T>::value, void>
+    >
+    void make_unique(Args&&...) = delete;
+
+    template<class T, class D>
+    void swap(unique_ptr<T, D>& lhs, unique_ptr<T, D>& rhs) noexcept
+    {
+        lhs.swap(rhs);
+    }
+
+    template<class T1, class D1, class T2, class D2>
+    bool operator==(const unique_ptr<T1, D1>& lhs,
+                    const unique_ptr<T2, D2>& rhs)
+    {
+        return lhs.get() == rhs.get();
+    }
+
+    template<class T1, class D1, class T2, class D2>
+    bool operator!=(const unique_ptr<T1, D1>& lhs,
+                    const unique_ptr<T2, D2>& rhs)
+    {
+        return lhs.get() != rhs.get();
+    }
+
+    template<class T1, class D1, class T2, class D2>
+    bool operator<(const unique_ptr<T1, D1>& lhs,
+                   const unique_ptr<T2, D2>& rhs)
+    {
+        return lhs.get() < rhs.get();
+    }
+
+    template<class T1, class D1, class T2, class D2>
+    bool operator<=(const unique_ptr<T1, D1>& lhs,
+                    const unique_ptr<T2, D2>& rhs)
+    {
+        return !(rhs < lhs);
+    }
+
+    template<class T1, class D1, class T2, class D2>
+    bool operator>(const unique_ptr<T1, D1>& lhs,
+                   const unique_ptr<T2, D2>& rhs)
+    {
+        return rhs < lhs;
+    }
+
+    template<class T1, class D1, class T2, class D2>
+    bool operator>=(const unique_ptr<T1, D1>& lhs,
+                    const unique_ptr<T2, D2>& rhs)
+    {
+        return !(lhs < rhs);
+    }
+
+    template<class T, class D>
+    bool operator==(const unique_ptr<T, D>& ptr, nullptr_t) noexcept
+    {
+        return !ptr;
+    }
+
+    template<class T, class D>
+    bool operator==(nullptr_t, const unique_ptr<T, D>& ptr) noexcept
+    {
+        return !ptr;
+    }
+
+    template<class T, class D>
+    bool operator!=(const unique_ptr<T, D>& ptr, nullptr_t) noexcept
+    {
+        return static_cast<bool>(ptr);
+    }
+
+    template<class T, class D>
+    bool operator!=(nullptr_t, const unique_ptr<T, D>& ptr) noexcept
+    {
+        return static_cast<bool>(ptr);
+    }
+
+    template<class T, class D>
+    bool operator<(const unique_ptr<T, D>& ptr, nullptr_t)
+    {
+        return ptr.get() < nullptr;
+    }
+
+    template<class T, class D>
+    bool operator<(nullptr_t, const unique_ptr<T, D>& ptr)
+    {
+        return nullptr < ptr.get();
+    }
+
+    template<class T, class D>
+    bool operator<=(const unique_ptr<T, D>& ptr, nullptr_t)
+    {
+        return !(nullptr < ptr);
+    }
+
+    template<class T, class D>
+    bool operator<=(nullptr_t, const unique_ptr<T, D>& ptr)
+    {
+        return !(ptr < nullptr);
+    }
+
+    template<class T, class D>
+    bool operator>(const unique_ptr<T, D>& ptr, nullptr_t)
+    {
+        return nullptr < ptr;
+    }
+
+    template<class T, class D>
+    bool operator>(nullptr_t, const unique_ptr<T, D>& ptr)
+    {
+        return ptr < nullptr;
+    }
+
+    template<class T, class D>
+    bool operator>=(const unique_ptr<T, D>& ptr, nullptr_t)
+    {
+        return !(ptr < nullptr);
+    }
+
+    template<class T, class D>
+    bool operator>=(nullptr_t, const unique_ptr<T, D>& ptr)
+    {
+        return !(nullptr < ptr);
+    }
 }
 
