Changeset bfc972e in mainline


Ignore:
Timestamp:
2018-07-05T21:41:24Z (6 years ago)
Author:
Dzejrou <dzejrou@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
ca8d393
Parents:
17012fcf
git-author:
Dzejrou <dzejrou@…> (2018-05-16 00:49:54)
git-committer:
Dzejrou <dzejrou@…> (2018-07-05 21:41:24)
Message:

cpp: moved type getters for allocator and pointer traits to a separate header, fully implemented pointer_traits and added pointer_traits tests

Location:
uspace/lib/cpp
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/cpp/include/impl/memory.hpp

    r17012fcf rbfc972e  
    3232#include <internal/aux.hpp>
    3333#include <internal/functional/hash.hpp>
     34#include <internal/memory/addressof.hpp>
    3435#include <internal/memory/allocator_arg.hpp>
    35 #include <internal/memory/addressof.hpp>
     36#include <internal/memory/type_getters.hpp>
    3637#include <iterator>
    3738#include <new>
     
    4344    /**
    4445     * 20.7.3, pointer traits:
     46     * Note: The type getters that are used in pointer_traits
     47     *       and allocator_traits are implemented in
     48     *       <internal/memory/type_getters.hpp>.
    4549     */
    4650
     
    4852    struct pointer_traits
    4953    {
    50         using pointer = Ptr;
    51         // TODO: element type, difference type
    52 
    53         // TODO: this is conditional, see standard
     54        using pointer         = Ptr;
     55        using element_type    = typename aux::ptr_get_element_type<Ptr>::type;
     56        using difference_type = typename aux::ptr_get_difference_type<Ptr>::type;
     57
    5458        template<class U>
    55         using rebind = typename Ptr::template rebind<U>;
     59        using rebind = typename aux::ptr_get_rebind<Ptr, U>::type;
     60
     61        static pointer pointer_to( // If is_void_t<element_type>, this type is unspecified.
     62            conditional_t<is_void_v<element_type>, char, element_type&> x
     63        )
     64        {
     65            return Ptr::pointer_to(x);
     66        }
    5667    };
     68
     69    template<class T>
     70    struct pointer_traits<T*>
     71    {
     72        using pointer         = T*;
     73        using element_type    = T;
     74        using difference_type = ptrdiff_t;
     75
     76        template<class U>
     77        using rebind = U*;
     78
     79        static pointer pointer_to(
     80            conditional_t<is_void_v<element_type>, char, element_type&> x
     81        )
     82        {
     83            return std::addressof(x);
     84        }
     85    };
     86
     87    /**
     88     * 20.7.4, pointer safety:
     89     */
     90
     91    // TODO: implement
     92
     93    /**
     94     * 20.7.5, align:
     95     */
     96
     97    // TODO: implement
    5798
    5899    /**
     
    84125     * 20.7.8, allocator traits:
    85126     */
    86 
    87     namespace aux
    88     {
    89         /**
    90          * The standard mandates that we reuse type from allocators
    91          * *if* they are defined or that we use something different.
    92          * These structures help us alternate between those by
    93          * using SFINAE.
    94          * TODO: Create tests for these!
    95          */
    96 
    97         template<class T, class = void>
    98         struct get_pointer: aux::type_is<typename T::value_type*>
    99         { /* DUMMY BODY */ };
    100 
    101         template<class T>
    102         struct get_pointer<T, void_t<typename T::pointer>>
    103             : aux::type_is<typename T::pointer>
    104         { /* DUMMY BODY */ };
    105 
    106         template<class T, class Ptr, class = void>
    107         struct get_const_pointer
    108             : aux::type_is<typename pointer_traits<Ptr>::template rebind<const typename T::value_type>>
    109         { /* DUMMY BODY */ };
    110 
    111         template<class T, class Ptr>
    112         struct get_const_pointer<T, Ptr, void_t<typename T::const_pointer>>
    113             : aux::type_is<typename T::const_pointer>
    114         { /* DUMMY BODY */ };
    115 
    116         template<class T, class Ptr, class = void>
    117         struct get_void_pointer
    118             : aux::type_is<typename pointer_traits<Ptr>::template rebind<void>>
    119         { /* DUMMY BODY */ };
    120 
    121         template<class T, class Ptr>
    122         struct get_void_pointer<T, Ptr, void_t<typename T::void_pointer>>
    123             : aux::type_is<typename T::void_pointer>
    124         { /* DUMMY BODY */ };
    125 
    126         template<class T, class Ptr, class = void>
    127         struct get_const_void_pointer
    128             : aux::type_is<typename pointer_traits<Ptr>::template rebind<const void>>
    129         { /* DUMMY BODY */ };
    130 
    131         template<class T, class Ptr>
    132         struct get_const_void_pointer<T, Ptr, void_t<typename T::const_void_pointer>>
    133             : aux::type_is<typename T::const_void_pointer>
    134         { /* DUMMY BODY */ };
    135 
    136         template<class T, class Ptr, class = void>
    137         struct get_difference_type
    138             : aux::type_is<typename pointer_traits<Ptr>::difference_type>
    139         { /* DUMMY BODY */ };
    140 
    141         template<class T, class Ptr>
    142         struct get_difference_type<T, Ptr, void_t<typename T::difference_type>>
    143             : aux::type_is<typename T::difference_type>
    144         { /* DUMMY BODY */ };
    145 
    146         template<class T, class Difference, class = void>
    147         struct get_size_type: aux::type_is<make_unsigned_t<Difference>>
    148         { /* DUMMY BODY */ };
    149 
    150         template<class T, class Difference>
    151         struct get_size_type<T, Difference, void_t<typename T::size_type>>
    152             : aux::type_is<typename T::size_type>
    153         { /* DUMMY BODY */ };
    154 
    155         template<class T, class = void>
    156         struct get_copy_propagate: aux::type_is<false_type>
    157         { /* DUMMY BODY */ };
    158 
    159         template<class T>
    160         struct get_copy_propagate<T, void_t<typename T::propagate_on_container_copy_assignment>>
    161             : aux::type_is<typename T::propagate_on_container_copy_assignment>
    162         { /* DUMMY BODY */ };
    163 
    164         template<class T, class = void>
    165         struct get_move_propagate: aux::type_is<false_type>
    166         { /* DUMMY BODY */ };
    167 
    168         template<class T>
    169         struct get_move_propagate<T, void_t<typename T::propagate_on_container_move_assignment>>
    170             : aux::type_is<typename T::propagate_on_container_move_assignment>
    171         { /* DUMMY BODY */ };
    172 
    173         template<class T, class = void>
    174         struct get_swap_propagate: aux::type_is<false_type>
    175         { /* DUMMY BODY */ };
    176 
    177         template<class T>
    178         struct get_swap_propagate<T, void_t<typename T::propagate_on_container_swap>>
    179             : aux::type_is<typename T::propagate_on_container_swap>
    180         { /* DUMMY BODY */ };
    181 
    182         template<class T, class = void>
    183         struct get_always_equal: aux::type_is<typename is_empty<T>::type>
    184         { /* DUMMY BODY */ };
    185 
    186         template<class T>
    187         struct get_always_equal<T, void_t<typename T::is_always_equal>>
    188             : aux::type_is<typename T::is_always_equal>
    189         { /* DUMMY BODY */ };
    190 
    191         template<class Alloc, class T, class = void>
    192         struct get_rebind_other
    193         { /* DUMMY BODY */ };
    194 
    195         template<class Alloc, class T>
    196         struct get_rebind_other<Alloc, T, void_t<typename Alloc::template rebind<T>::other>>
    197             : aux::type_is<typename Alloc::template rebind<T>::other>
    198         { /* DUMMY BODY */ };
    199 
    200         /* TODO: How am I suppose to do this?!
    201         template<template<class T, class... Args> class Alloc>
    202         struct get_rebind_args;
    203         */
    204 
    205         template<class Alloc, class T>
    206         struct get_rebind_args: aux::type_is<typename get_rebind_other<Alloc, T>::type>
    207         { /* DUMMY BODY */ };
    208     }
    209127
    210128    template<class Alloc>
  • uspace/lib/cpp/include/internal/test/tests.hpp

    r17012fcf rbfc972e  
    252252        private:
    253253            void test_unique_ptr();
     254            void test_shared_ptr();
     255            void test_weak_ptr();
     256            void test_allocators();
     257            void test_pointers();
    254258    };
    255259}
  • uspace/lib/cpp/src/internal/test/memory.cpp

    r17012fcf rbfc972e  
    3131#include <internal/test/tests.hpp>
    3232#include <memory>
     33#include <type_traits>
    3334#include <utility>
    3435
    3536namespace std::test
    3637{
     38    namespace aux
     39    {
     40        struct dummy_pointer1
     41        {
     42            using element_type    = int;
     43            using difference_type = bool;
     44
     45            template<class U>
     46            using rebind = unsigned;
     47
     48            int tag{};
     49
     50            static dummy_pointer1 pointer_to(element_type& x)
     51            {
     52                dummy_pointer1 res;
     53                res.tag = x;
     54                return res;
     55            }
     56        };
     57
     58        template<class T, class... Args>
     59        struct dummy_pointer2
     60        {
     61            using element_type    = signed char;
     62            using difference_type = unsigned char;
     63        };
     64
     65        struct dummy_allocator1
     66        {
     67            using value_type = int;
     68        };
     69
     70        struct dummy_allocator2
     71        {
     72            using value_type    = int;
     73            using pointer       = char*;
     74            using const_pointer = const void*;
     75        };
     76    }
     77
    3778    bool memory_test::run(bool report)
    3879    {
     
    4283        test_unique_ptr();
    4384        test_shared_ptr();
     85        test_weak_ptr();
     86        test_allocators();
     87        test_pointers();
    4488
    4589        return end();
     
    110154            {
    111155                auto ptr2 = ptr1;
    112                 test_eq("shared_ptr copy pt1", ptr1.use_count(), 2U);
    113                 test_eq("shared_ptr copy pt2", ptr2.use_count(), 2U);
     156                test_eq("shared_ptr copy pt1", ptr1.use_count(), 2L);
     157                test_eq("shared_ptr copy pt2", ptr2.use_count(), 2L);
    114158                test_eq("shared_ptr copy no constructor call", mock::copy_constructor_calls, 0U);
    115159                test_eq("shared_ptr not unique", ptr1.unique(), false);
    116160
    117161                auto ptr3 = std::move(ptr2);
    118                 test_eq("shared_ptr move pt1", ptr1.use_count(), 2U);
    119                 test_eq("shared_ptr move pt2", ptr3.use_count(), 2U);
     162                test_eq("shared_ptr move pt1", ptr1.use_count(), 2L);
     163                test_eq("shared_ptr move pt2", ptr3.use_count(), 2L);
     164                test_eq("shared_ptr move pt3", ptr2.use_count(), 0L);
    120165
    121166                test_eq("shared_ptr move origin empty", (bool)ptr2, false);
     
    125170        test_eq("shared_ptr original out of scope", mock::destructor_calls, 1U);
    126171    }
     172
     173    void memory_test::test_weak_ptr()
     174    {
     175        mock::clear();
     176        {
     177            std::weak_ptr<mock> wptr1{};
     178            {
     179                auto ptr1 = std::make_shared<mock>();
     180                wptr1 = ptr1;
     181                {
     182                    std::weak_ptr<mock> wptr2 = ptr1;
     183                    test_eq("weak_ptr shares use count", wptr2.use_count(), 1L);
     184                    test_eq("weak_ptr not expired", wptr2.expired(), false);
     185
     186                    auto ptr2 = wptr2.lock();
     187                    test_eq("locked ptr increases use count", ptr1.use_count(), 2L);
     188                }
     189            }
     190            test_eq("weak_ptr expired after all shared_ptrs die", wptr1.expired(), true);
     191            test_eq("shared object destroyed while weak_ptr exists", mock::destructor_calls, 1U);
     192        }
     193    }
     194
     195    void memory_test::test_allocators()
     196    {
     197        using dummy_traits1 = std::allocator_traits<aux::dummy_allocator1>;
     198        using dummy_traits2 = std::allocator_traits<aux::dummy_allocator2>;
     199
     200        /* static_assert(std::is_same_v<typename dummy_traits1::pointer, int*>); */
     201        /* static_assert(std::is_same_v<typename dummy_traits2::pointer, char*>); */
     202    }
     203
     204    void memory_test::test_pointers()
     205    {
     206        using dummy_traits1 = std::pointer_traits<aux::dummy_pointer1>;
     207        using dummy_traits2 = std::pointer_traits<aux::dummy_pointer2<int, char>>;
     208        using int_traits    = std::pointer_traits<int*>;
     209
     210        static_assert(std::is_same_v<typename dummy_traits1::pointer, aux::dummy_pointer1>);
     211        static_assert(std::is_same_v<typename dummy_traits1::element_type, int>);
     212        static_assert(std::is_same_v<typename dummy_traits1::difference_type, bool>);
     213        static_assert(std::is_same_v<typename dummy_traits1::template rebind<long>, unsigned>);
     214
     215        int x{10};
     216        test_eq("pointer_traits<Ptr>::pointer_to", dummy_traits1::pointer_to(x).tag, 10);
     217
     218        static_assert(std::is_same_v<typename dummy_traits2::pointer, aux::dummy_pointer2<int, char>>);
     219        static_assert(std::is_same_v<typename dummy_traits2::element_type, signed char>);
     220        static_assert(std::is_same_v<typename dummy_traits2::difference_type, unsigned char>);
     221
     222        static_assert(std::is_same_v<typename int_traits::pointer, int*>);
     223        static_assert(std::is_same_v<typename int_traits::element_type, int>);
     224        static_assert(std::is_same_v<typename int_traits::difference_type, ptrdiff_t>);
     225        static_assert(std::is_same_v<typename int_traits::rebind<char>, char*>);
     226    }
    127227}
Note: See TracChangeset for help on using the changeset viewer.