Home | History | Annotate | Line # | Download | only in experimental
      1 // <experimental/memory> -*- C++ -*-
      2 
      3 // Copyright (C) 2015-2022 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file experimental/memory
     26  *  This is a TS C++ Library header.
     27  *  @ingroup libfund-ts
     28  */
     29 
     30 //
     31 // N4336 Working Draft, C++ Extensions for Library Fundamentals, Version 2
     32 //
     33 
     34 #ifndef _GLIBCXX_EXPERIMENTAL_MEMORY
     35 #define _GLIBCXX_EXPERIMENTAL_MEMORY 1
     36 
     37 #pragma GCC system_header
     38 
     39 #if __cplusplus >= 201402L
     40 
     41 #include <memory>
     42 #include <type_traits>
     43 #include <experimental/bits/shared_ptr.h>
     44 #include <bits/functional_hash.h>
     45 
     46 namespace std _GLIBCXX_VISIBILITY(default)
     47 {
     48 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     49 
     50 namespace experimental
     51 {
     52 inline namespace fundamentals_v2
     53 {
     54 #define __cpp_lib_experimental_observer_ptr 201411
     55 
     56   template <typename _Tp>
     57     class observer_ptr
     58     {
     59     public:
     60       // publish our template parameter and variations thereof
     61       using element_type = _Tp;
     62       using __pointer = add_pointer_t<_Tp>;            // exposition-only
     63       using __reference = add_lvalue_reference_t<_Tp>; // exposition-only
     64 
     65       // 3.2.2, observer_ptr constructors
     66       // default c'tor
     67       constexpr observer_ptr() noexcept
     68       : __t()
     69       { }
     70 
     71       // pointer-accepting c'tors
     72       constexpr observer_ptr(nullptr_t) noexcept
     73       : __t()
     74       { }
     75 
     76       constexpr explicit observer_ptr(__pointer __p) noexcept
     77       : __t(__p)
     78       { }
     79 
     80       // copying c'tors (in addition to compiler-generated copy c'tor)
     81       template <typename _Up,
     82 		typename = typename enable_if<
     83 		  is_convertible<typename add_pointer<_Up>::type, __pointer
     84 		  >::value
     85 		>::type>
     86       constexpr observer_ptr(observer_ptr<_Up> __p) noexcept
     87       : __t(__p.get())
     88       {
     89       }
     90 
     91       // 3.2.3, observer_ptr observers
     92       constexpr __pointer
     93       get() const noexcept
     94       {
     95 	return __t;
     96       }
     97 
     98       constexpr __reference
     99       operator*() const
    100       {
    101 	return *get();
    102       }
    103 
    104       constexpr __pointer
    105       operator->() const noexcept
    106       {
    107 	return get();
    108       }
    109 
    110       constexpr explicit operator bool() const noexcept
    111       {
    112 	return get() != nullptr;
    113       }
    114 
    115       // 3.2.4, observer_ptr conversions
    116       constexpr explicit operator __pointer() const noexcept
    117       {
    118 	return get();
    119       }
    120 
    121       // 3.2.5, observer_ptr modifiers
    122       constexpr __pointer
    123       release() noexcept
    124       {
    125 	__pointer __tmp = get();
    126 	reset();
    127 	return __tmp;
    128       }
    129 
    130       constexpr void
    131       reset(__pointer __p = nullptr) noexcept
    132       {
    133 	__t = __p;
    134       }
    135 
    136       constexpr void
    137       swap(observer_ptr& __p) noexcept
    138       {
    139 	std::swap(__t, __p.__t);
    140       }
    141 
    142     private:
    143       __pointer __t;
    144     }; // observer_ptr<>
    145 
    146   template<typename _Tp>
    147     void
    148     swap(observer_ptr<_Tp>& __p1, observer_ptr<_Tp>& __p2) noexcept
    149     {
    150       __p1.swap(__p2);
    151     }
    152 
    153   template<typename _Tp>
    154     observer_ptr<_Tp>
    155     make_observer(_Tp* __p) noexcept
    156     {
    157       return observer_ptr<_Tp>(__p);
    158     }
    159 
    160   template<typename _Tp, typename _Up>
    161     bool
    162     operator==(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
    163     {
    164       return __p1.get() == __p2.get();
    165     }
    166 
    167   template<typename _Tp, typename _Up>
    168     bool
    169     operator!=(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
    170     {
    171     return !(__p1 == __p2);
    172     }
    173 
    174   template<typename _Tp>
    175     bool
    176     operator==(observer_ptr<_Tp> __p, nullptr_t) noexcept
    177     {
    178       return !__p;
    179     }
    180 
    181   template<typename _Tp>
    182     bool
    183     operator==(nullptr_t, observer_ptr<_Tp> __p) noexcept
    184     {
    185       return !__p;
    186     }
    187 
    188   template<typename _Tp>
    189     bool
    190     operator!=(observer_ptr<_Tp> __p, nullptr_t) noexcept
    191     {
    192       return bool(__p);
    193     }
    194 
    195   template<typename _Tp>
    196     bool
    197     operator!=(nullptr_t, observer_ptr<_Tp> __p) noexcept
    198     {
    199       return bool(__p);
    200     }
    201 
    202   template<typename _Tp, typename _Up>
    203     bool
    204     operator<(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
    205     {
    206       return std::less<typename common_type<typename add_pointer<_Tp>::type,
    207 					    typename add_pointer<_Up>::type
    208 					    >::type
    209 		       >{}(__p1.get(), __p2.get());
    210     }
    211 
    212   template<typename _Tp, typename _Up>
    213     bool
    214     operator>(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
    215     {
    216       return __p2 < __p1;
    217     }
    218 
    219   template<typename _Tp, typename _Up>
    220     bool
    221     operator<=(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
    222     {
    223       return !(__p2 < __p1);
    224     }
    225 
    226   template<typename _Tp, typename _Up>
    227     bool
    228     operator>=(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
    229     {
    230       return !(__p1 < __p2);
    231     }
    232 } // namespace fundamentals_v2
    233 } // namespace experimental
    234 
    235 template <typename _Tp>
    236   struct hash<experimental::observer_ptr<_Tp>>
    237   {
    238     using result_type = size_t;
    239     using argument_type = experimental::observer_ptr<_Tp>;
    240 
    241     size_t
    242     operator()(const experimental::observer_ptr<_Tp>& __t) const
    243     noexcept(noexcept(hash<typename add_pointer<_Tp>::type> {}(__t.get())))
    244     {
    245       return hash<typename add_pointer<_Tp>::type> {}(__t.get());
    246     }
    247   };
    248 
    249 
    250 _GLIBCXX_END_NAMESPACE_VERSION
    251 } // namespace std
    252 
    253 #endif // __cplusplus <= 201103L
    254 
    255 #endif // _GLIBCXX_EXPERIMENTAL_MEMORY
    256