Index: uspace/lib/cpp/include/impl/memory.hpp
===================================================================
--- uspace/lib/cpp/include/impl/memory.hpp	(revision 17012fcfd36baac8e9c996cc80248789a87d6308)
+++ uspace/lib/cpp/include/impl/memory.hpp	(revision bfc972ed291255d220c32e502dd15b876c99e8d6)
@@ -32,6 +32,7 @@
 #include <internal/aux.hpp>
 #include <internal/functional/hash.hpp>
+#include <internal/memory/addressof.hpp>
 #include <internal/memory/allocator_arg.hpp>
-#include <internal/memory/addressof.hpp>
+#include <internal/memory/type_getters.hpp>
 #include <iterator>
 #include <new>
@@ -43,4 +44,7 @@
     /**
      * 20.7.3, pointer traits:
+     * Note: The type getters that are used in pointer_traits
+     *       and allocator_traits are implemented in
+     *       <internal/memory/type_getters.hpp>.
      */
 
@@ -48,11 +52,48 @@
     struct pointer_traits
     {
-        using pointer = Ptr;
-        // TODO: element type, difference type
-
-        // TODO: this is conditional, see standard
+        using pointer         = Ptr;
+        using element_type    = typename aux::ptr_get_element_type<Ptr>::type;
+        using difference_type = typename aux::ptr_get_difference_type<Ptr>::type;
+
         template<class U>
-        using rebind = typename Ptr::template rebind<U>;
+        using rebind = typename aux::ptr_get_rebind<Ptr, U>::type;
+
+        static pointer pointer_to( // If is_void_t<element_type>, this type is unspecified.
+            conditional_t<is_void_v<element_type>, char, element_type&> x
+        )
+        {
+            return Ptr::pointer_to(x);
+        }
     };
+
+    template<class T>
+    struct pointer_traits<T*>
+    {
+        using pointer         = T*;
+        using element_type    = T;
+        using difference_type = ptrdiff_t;
+
+        template<class U>
+        using rebind = U*;
+
+        static pointer pointer_to(
+            conditional_t<is_void_v<element_type>, char, element_type&> x
+        )
+        {
+            return std::addressof(x);
+        }
+    };
+
+    /**
+     * 20.7.4, pointer safety:
+     */
+
+    // TODO: implement
+
+    /**
+     * 20.7.5, align:
+     */
+
+    // TODO: implement
 
     /**
@@ -84,127 +125,4 @@
      * 20.7.8, allocator traits:
      */
-
-    namespace aux
-    {
-        /**
-         * The standard mandates that we reuse type from allocators
-         * *if* they are defined or that we use something different.
-         * These structures help us alternate between those by
-         * using SFINAE.
-         * TODO: Create tests for these!
-         */
-
-        template<class T, class = void>
-        struct get_pointer: aux::type_is<typename T::value_type*>
-        { /* DUMMY BODY */ };
-
-        template<class T>
-        struct get_pointer<T, void_t<typename T::pointer>>
-            : aux::type_is<typename T::pointer>
-        { /* DUMMY BODY */ };
-
-        template<class T, class Ptr, class = void>
-        struct get_const_pointer
-            : aux::type_is<typename pointer_traits<Ptr>::template rebind<const typename T::value_type>>
-        { /* DUMMY BODY */ };
-
-        template<class T, class Ptr>
-        struct get_const_pointer<T, Ptr, void_t<typename T::const_pointer>>
-            : aux::type_is<typename T::const_pointer>
-        { /* DUMMY BODY */ };
-
-        template<class T, class Ptr, class = void>
-        struct get_void_pointer
-            : aux::type_is<typename pointer_traits<Ptr>::template rebind<void>>
-        { /* DUMMY BODY */ };
-
-        template<class T, class Ptr>
-        struct get_void_pointer<T, Ptr, void_t<typename T::void_pointer>>
-            : aux::type_is<typename T::void_pointer>
-        { /* DUMMY BODY */ };
-
-        template<class T, class Ptr, class = void>
-        struct get_const_void_pointer
-            : aux::type_is<typename pointer_traits<Ptr>::template rebind<const void>>
-        { /* DUMMY BODY */ };
-
-        template<class T, class Ptr>
-        struct get_const_void_pointer<T, Ptr, void_t<typename T::const_void_pointer>>
-            : aux::type_is<typename T::const_void_pointer>
-        { /* DUMMY BODY */ };
-
-        template<class T, class Ptr, class = void>
-        struct get_difference_type
-            : aux::type_is<typename pointer_traits<Ptr>::difference_type>
-        { /* DUMMY BODY */ };
-
-        template<class T, class Ptr>
-        struct get_difference_type<T, Ptr, void_t<typename T::difference_type>>
-            : aux::type_is<typename T::difference_type>
-        { /* DUMMY BODY */ };
-
-        template<class T, class Difference, class = void>
-        struct get_size_type: aux::type_is<make_unsigned_t<Difference>>
-        { /* DUMMY BODY */ };
-
-        template<class T, class Difference>
-        struct get_size_type<T, Difference, void_t<typename T::size_type>>
-            : aux::type_is<typename T::size_type>
-        { /* DUMMY BODY */ };
-
-        template<class T, class = void>
-        struct get_copy_propagate: aux::type_is<false_type>
-        { /* DUMMY BODY */ };
-
-        template<class T>
-        struct get_copy_propagate<T, void_t<typename T::propagate_on_container_copy_assignment>>
-            : aux::type_is<typename T::propagate_on_container_copy_assignment>
-        { /* DUMMY BODY */ };
-
-        template<class T, class = void>
-        struct get_move_propagate: aux::type_is<false_type>
-        { /* DUMMY BODY */ };
-
-        template<class T>
-        struct get_move_propagate<T, void_t<typename T::propagate_on_container_move_assignment>>
-            : aux::type_is<typename T::propagate_on_container_move_assignment>
-        { /* DUMMY BODY */ };
-
-        template<class T, class = void>
-        struct get_swap_propagate: aux::type_is<false_type>
-        { /* DUMMY BODY */ };
-
-        template<class T>
-        struct get_swap_propagate<T, void_t<typename T::propagate_on_container_swap>>
-            : aux::type_is<typename T::propagate_on_container_swap>
-        { /* DUMMY BODY */ };
-
-        template<class T, class = void>
-        struct get_always_equal: aux::type_is<typename is_empty<T>::type>
-        { /* DUMMY BODY */ };
-
-        template<class T>
-        struct get_always_equal<T, void_t<typename T::is_always_equal>>
-            : aux::type_is<typename T::is_always_equal>
-        { /* DUMMY BODY */ };
-
-        template<class Alloc, class T, class = void>
-        struct get_rebind_other
-        { /* DUMMY BODY */ };
-
-        template<class Alloc, class T>
-        struct get_rebind_other<Alloc, T, void_t<typename Alloc::template rebind<T>::other>>
-            : aux::type_is<typename Alloc::template rebind<T>::other>
-        { /* DUMMY BODY */ };
-
-        /* TODO: How am I suppose to do this?!
-        template<template<class T, class... Args> class Alloc>
-        struct get_rebind_args;
-        */
-
-        template<class Alloc, class T>
-        struct get_rebind_args: aux::type_is<typename get_rebind_other<Alloc, T>::type>
-        { /* DUMMY BODY */ };
-    }
 
     template<class Alloc>
Index: uspace/lib/cpp/include/internal/memory/type_getters.hpp
===================================================================
--- uspace/lib/cpp/include/internal/memory/type_getters.hpp	(revision bfc972ed291255d220c32e502dd15b876c99e8d6)
+++ uspace/lib/cpp/include/internal/memory/type_getters.hpp	(revision bfc972ed291255d220c32e502dd15b876c99e8d6)
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2017 Jaroslav Jindrak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBCPP_INTERNAL_MEMORY_TYPE_GETTERS
+#define LIBCPP_INTERNAL_MEMORY_TYPE_GETTERS
+
+/**
+ * Allocator and pointer traits require us to provide
+ * conditional typedefs based on whether the wrapped
+ * allocator contains them or not. To avoid unnecessary
+ * code clutter in <memory>, we moved them to their
+ * separate header (though note that these metafunctions
+ * have no use outside of <memory>).
+ */
+
+#include <cstddef>
+#include <internal/aux.hpp>
+#include <type_traits>
+
+namespace std
+{
+    template<class T>
+    struct pointer_traits;
+}
+
+namespace std::aux
+{
+    /**
+     * Pointer traits:
+     */
+
+    template<class Ptr, class = void>
+    struct ptr_get_element_type
+    { /* DUMMY BODY */ };
+
+    template<class Ptr>
+    struct ptr_get_element_type<Ptr, void_t<typename Ptr::element_type>>
+        : aux::type_is<typename Ptr::element_type>
+    { /* DUMMY BODY */ };
+
+    template<template <class, class...> class Ptr, class T, class... Args>
+    struct ptr_get_element_type<
+        Ptr<T, Args...>, void_t<typename Ptr<T, Args...>::element_type>
+    >: aux::type_is<typename Ptr<T, Args...>::element_type>
+    { /* DUMMY BODY */ };
+
+    template<class Ptr, class = void>
+    struct ptr_get_difference_type: aux::type_is<ptrdiff_t>
+    { /* DUMMY BODY */ };
+
+    template<class Ptr>
+    struct ptr_get_difference_type<Ptr, void_t<typename Ptr::difference_type>>
+        : aux::type_is<typename Ptr::difference_type>
+    { /* DUMMY BODY */ };
+
+    template<class Ptr, class U, class = void>
+    struct ptr_get_rebind
+    { /* DUMMY BODY */ };
+
+    template<class Ptr, class U>
+    struct ptr_get_rebind<Ptr, U, void_t<typename Ptr::template rebind<U>>>
+        : aux::type_is<typename Ptr::template rebind<U>>
+    { /* DUMMY BODY */ };
+
+    template<template <class, class...> class Ptr, class T, class... Args, class U>
+    struct ptr_get_rebind<Ptr<T, Args...>, U>
+        : aux::type_is<Ptr<U, Args...>>
+    { /* DUMMY BODY */ };
+
+    /**
+     * Allocator traits:
+     */
+
+    template<class T, class = void>
+    struct get_pointer: aux::type_is<typename T::value_type*>
+    { /* DUMMY BODY */ };
+
+    template<class T>
+    struct get_pointer<T, void_t<typename T::pointer>>
+        : aux::type_is<typename T::pointer>
+    { /* DUMMY BODY */ };
+
+    template<class T, class Ptr, class = void>
+    struct get_const_pointer
+        : aux::type_is<typename pointer_traits<Ptr>::template rebind<const typename T::value_type>>
+    { /* DUMMY BODY */ };
+
+    template<class T, class Ptr>
+    struct get_const_pointer<T, Ptr, void_t<typename T::const_pointer>>
+        : aux::type_is<typename T::const_pointer>
+    { /* DUMMY BODY */ };
+
+    template<class T, class Ptr, class = void>
+    struct get_void_pointer
+        : aux::type_is<typename pointer_traits<Ptr>::template rebind<void>>
+    { /* DUMMY BODY */ };
+
+    template<class T, class Ptr>
+    struct get_void_pointer<T, Ptr, void_t<typename T::void_pointer>>
+        : aux::type_is<typename T::void_pointer>
+    { /* DUMMY BODY */ };
+
+    template<class T, class Ptr, class = void>
+    struct get_const_void_pointer
+        : aux::type_is<typename pointer_traits<Ptr>::template rebind<const void>>
+    { /* DUMMY BODY */ };
+
+    template<class T, class Ptr>
+    struct get_const_void_pointer<T, Ptr, void_t<typename T::const_void_pointer>>
+        : aux::type_is<typename T::const_void_pointer>
+    { /* DUMMY BODY */ };
+
+    template<class T, class Ptr, class = void>
+    struct get_difference_type
+        : aux::type_is<typename pointer_traits<Ptr>::difference_type>
+    { /* DUMMY BODY */ };
+
+    template<class T, class Ptr>
+    struct get_difference_type<T, Ptr, void_t<typename T::difference_type>>
+        : aux::type_is<typename T::difference_type>
+    { /* DUMMY BODY */ };
+
+    template<class T, class Difference, class = void>
+    struct get_size_type: aux::type_is<make_unsigned_t<Difference>>
+    { /* DUMMY BODY */ };
+
+    template<class T, class Difference>
+    struct get_size_type<T, Difference, void_t<typename T::size_type>>
+        : aux::type_is<typename T::size_type>
+    { /* DUMMY BODY */ };
+
+    template<class T, class = void>
+    struct get_copy_propagate: aux::type_is<false_type>
+    { /* DUMMY BODY */ };
+
+    template<class T>
+    struct get_copy_propagate<T, void_t<typename T::propagate_on_container_copy_assignment>>
+        : aux::type_is<typename T::propagate_on_container_copy_assignment>
+    { /* DUMMY BODY */ };
+
+    template<class T, class = void>
+    struct get_move_propagate: aux::type_is<false_type>
+    { /* DUMMY BODY */ };
+
+    template<class T>
+    struct get_move_propagate<T, void_t<typename T::propagate_on_container_move_assignment>>
+        : aux::type_is<typename T::propagate_on_container_move_assignment>
+    { /* DUMMY BODY */ };
+
+    template<class T, class = void>
+    struct get_swap_propagate: aux::type_is<false_type>
+    { /* DUMMY BODY */ };
+
+    template<class T>
+    struct get_swap_propagate<T, void_t<typename T::propagate_on_container_swap>>
+        : aux::type_is<typename T::propagate_on_container_swap>
+    { /* DUMMY BODY */ };
+
+    template<class T, class = void>
+    struct get_always_equal: aux::type_is<typename is_empty<T>::type>
+    { /* DUMMY BODY */ };
+
+    template<class T>
+    struct get_always_equal<T, void_t<typename T::is_always_equal>>
+        : aux::type_is<typename T::is_always_equal>
+    { /* DUMMY BODY */ };
+
+    template<class Alloc, class T, class = void>
+    struct get_rebind_other
+    { /* DUMMY BODY */ };
+
+    template<class Alloc, class T>
+    struct get_rebind_other<Alloc, T, void_t<typename Alloc::template rebind<T>::other>>
+        : aux::type_is<typename Alloc::template rebind<T>::other>
+    { /* DUMMY BODY */ };
+
+    /* TODO: How am I suppose to do this?!
+    template<template<class T, class... Args> class Alloc>
+    struct get_rebind_args;
+    */
+
+    template<class Alloc, class T>
+    struct get_rebind_args: aux::type_is<typename get_rebind_other<Alloc, T>::type>
+    { /* DUMMY BODY */ };
+}
+
+#endif
Index: uspace/lib/cpp/include/internal/test/tests.hpp
===================================================================
--- uspace/lib/cpp/include/internal/test/tests.hpp	(revision 17012fcfd36baac8e9c996cc80248789a87d6308)
+++ uspace/lib/cpp/include/internal/test/tests.hpp	(revision bfc972ed291255d220c32e502dd15b876c99e8d6)
@@ -252,4 +252,8 @@
         private:
             void test_unique_ptr();
+            void test_shared_ptr();
+            void test_weak_ptr();
+            void test_allocators();
+            void test_pointers();
     };
 }
Index: uspace/lib/cpp/src/internal/test/memory.cpp
===================================================================
--- uspace/lib/cpp/src/internal/test/memory.cpp	(revision 17012fcfd36baac8e9c996cc80248789a87d6308)
+++ uspace/lib/cpp/src/internal/test/memory.cpp	(revision bfc972ed291255d220c32e502dd15b876c99e8d6)
@@ -31,8 +31,49 @@
 #include <internal/test/tests.hpp>
 #include <memory>
+#include <type_traits>
 #include <utility>
 
 namespace std::test
 {
+    namespace aux
+    {
+        struct dummy_pointer1
+        {
+            using element_type    = int;
+            using difference_type = bool;
+
+            template<class U>
+            using rebind = unsigned;
+
+            int tag{};
+
+            static dummy_pointer1 pointer_to(element_type& x)
+            {
+                dummy_pointer1 res;
+                res.tag = x;
+                return res;
+            }
+        };
+
+        template<class T, class... Args>
+        struct dummy_pointer2
+        {
+            using element_type    = signed char;
+            using difference_type = unsigned char;
+        };
+
+        struct dummy_allocator1
+        {
+            using value_type = int;
+        };
+
+        struct dummy_allocator2
+        {
+            using value_type    = int;
+            using pointer       = char*;
+            using const_pointer = const void*;
+        };
+    }
+
     bool memory_test::run(bool report)
     {
@@ -42,4 +83,7 @@
         test_unique_ptr();
         test_shared_ptr();
+        test_weak_ptr();
+        test_allocators();
+        test_pointers();
 
         return end();
@@ -110,12 +154,13 @@
             {
                 auto ptr2 = ptr1;
-                test_eq("shared_ptr copy pt1", ptr1.use_count(), 2U);
-                test_eq("shared_ptr copy pt2", ptr2.use_count(), 2U);
+                test_eq("shared_ptr copy pt1", ptr1.use_count(), 2L);
+                test_eq("shared_ptr copy pt2", ptr2.use_count(), 2L);
                 test_eq("shared_ptr copy no constructor call", mock::copy_constructor_calls, 0U);
                 test_eq("shared_ptr not unique", ptr1.unique(), false);
 
                 auto ptr3 = std::move(ptr2);
-                test_eq("shared_ptr move pt1", ptr1.use_count(), 2U);
-                test_eq("shared_ptr move pt2", ptr3.use_count(), 2U);
+                test_eq("shared_ptr move pt1", ptr1.use_count(), 2L);
+                test_eq("shared_ptr move pt2", ptr3.use_count(), 2L);
+                test_eq("shared_ptr move pt3", ptr2.use_count(), 0L);
 
                 test_eq("shared_ptr move origin empty", (bool)ptr2, false);
@@ -125,3 +170,58 @@
         test_eq("shared_ptr original out of scope", mock::destructor_calls, 1U);
     }
+
+    void memory_test::test_weak_ptr()
+    {
+        mock::clear();
+        {
+            std::weak_ptr<mock> wptr1{};
+            {
+                auto ptr1 = std::make_shared<mock>();
+                wptr1 = ptr1;
+                {
+                    std::weak_ptr<mock> wptr2 = ptr1;
+                    test_eq("weak_ptr shares use count", wptr2.use_count(), 1L);
+                    test_eq("weak_ptr not expired", wptr2.expired(), false);
+
+                    auto ptr2 = wptr2.lock();
+                    test_eq("locked ptr increases use count", ptr1.use_count(), 2L);
+                }
+            }
+            test_eq("weak_ptr expired after all shared_ptrs die", wptr1.expired(), true);
+            test_eq("shared object destroyed while weak_ptr exists", mock::destructor_calls, 1U);
+        }
+    }
+
+    void memory_test::test_allocators()
+    {
+        using dummy_traits1 = std::allocator_traits<aux::dummy_allocator1>;
+        using dummy_traits2 = std::allocator_traits<aux::dummy_allocator2>;
+
+        /* static_assert(std::is_same_v<typename dummy_traits1::pointer, int*>); */
+        /* static_assert(std::is_same_v<typename dummy_traits2::pointer, char*>); */
+    }
+
+    void memory_test::test_pointers()
+    {
+        using dummy_traits1 = std::pointer_traits<aux::dummy_pointer1>;
+        using dummy_traits2 = std::pointer_traits<aux::dummy_pointer2<int, char>>;
+        using int_traits    = std::pointer_traits<int*>;
+
+        static_assert(std::is_same_v<typename dummy_traits1::pointer, aux::dummy_pointer1>);
+        static_assert(std::is_same_v<typename dummy_traits1::element_type, int>);
+        static_assert(std::is_same_v<typename dummy_traits1::difference_type, bool>);
+        static_assert(std::is_same_v<typename dummy_traits1::template rebind<long>, unsigned>);
+
+        int x{10};
+        test_eq("pointer_traits<Ptr>::pointer_to", dummy_traits1::pointer_to(x).tag, 10);
+
+        static_assert(std::is_same_v<typename dummy_traits2::pointer, aux::dummy_pointer2<int, char>>);
+        static_assert(std::is_same_v<typename dummy_traits2::element_type, signed char>);
+        static_assert(std::is_same_v<typename dummy_traits2::difference_type, unsigned char>);
+
+        static_assert(std::is_same_v<typename int_traits::pointer, int*>);
+        static_assert(std::is_same_v<typename int_traits::element_type, int>);
+        static_assert(std::is_same_v<typename int_traits::difference_type, ptrdiff_t>);
+        static_assert(std::is_same_v<typename int_traits::rebind<char>, char*>);
+    }
 }
