Home | History | Annotate | Line # | Download | only in experimental
      1 // <experimental/memory> -*- C++ -*-
      2 
      3 // Copyright (C) 2015-2024 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 #include <bits/requires_hosted.h> // experimental is currently omitted
     40 
     41 #if __cplusplus >= 201402L
     42 
     43 #include <memory>
     44 #include <type_traits>
     45 #include <experimental/bits/shared_ptr.h>
     46 #include <bits/functional_hash.h>
     47 
     48 namespace std _GLIBCXX_VISIBILITY(default)
     49 {
     50 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     51 
     52 namespace experimental
     53 {
     54 inline namespace fundamentals_v2
     55 {
     56 #define __cpp_lib_experimental_observer_ptr 201411
     57 
     58   template <typename _Tp>
     59     class observer_ptr
     60     {
     61     public:
     62       // publish our template parameter and variations thereof
     63       using element_type = _Tp;
     64       using __pointer = add_pointer_t<_Tp>;            // exposition-only
     65       using __reference = add_lvalue_reference_t<_Tp>; // exposition-only
     66 
     67       // 3.2.2, observer_ptr constructors
     68       // default c'tor
     69       constexpr observer_ptr() noexcept
     70       : __t()
     71       { }
     72 
     73       // pointer-accepting c'tors
     74       constexpr observer_ptr(nullptr_t) noexcept
     75       : __t()
     76       { }
     77 
     78       constexpr explicit observer_ptr(__pointer __p) noexcept
     79       : __t(__p)
     80       { }
     81 
     82       // copying c'tors (in addition to compiler-generated copy c'tor)
     83       template <typename _Up,
     84 		typename = typename enable_if<
     85 		  is_convertible<typename add_pointer<_Up>::type, __pointer
     86 		  >::value
     87 		>::type>
     88       constexpr observer_ptr(observer_ptr<_Up> __p) noexcept
     89       : __t(__p.get())
     90       {
     91       }
     92 
     93       // 3.2.3, observer_ptr observers
     94       constexpr __pointer
     95       get() const noexcept
     96       {
     97 	return __t;
     98       }
     99 
    100       constexpr __reference
    101       operator*() const
    102       {
    103 	return *get();
    104       }
    105 
    106       constexpr __pointer
    107       operator->() const noexcept
    108       {
    109 	return get();
    110       }
    111 
    112       constexpr explicit operator bool() const noexcept
    113       {
    114 	return get() != nullptr;
    115       }
    116 
    117       // 3.2.4, observer_ptr conversions
    118       constexpr explicit operator __pointer() const noexcept
    119       {
    120 	return get();
    121       }
    122 
    123       // 3.2.5, observer_ptr modifiers
    124       constexpr __pointer
    125       release() noexcept
    126       {
    127 	__pointer __tmp = get();
    128 	reset();
    129 	return __tmp;
    130       }
    131 
    132       constexpr void
    133       reset(__pointer __p = nullptr) noexcept
    134       {
    135 	__t = __p;
    136       }
    137 
    138       constexpr void
    139       swap(observer_ptr& __p) noexcept
    140       {
    141 	std::swap(__t, __p.__t);
    142       }
    143 
    144     private:
    145       __pointer __t;
    146     }; // observer_ptr<>
    147 
    148   template<typename _Tp>
    149     void
    150     swap(observer_ptr<_Tp>& __p1, observer_ptr<_Tp>& __p2) noexcept
    151     {
    152       __p1.swap(__p2);
    153     }
    154 
    155   template<typename _Tp>
    156     observer_ptr<_Tp>
    157     make_observer(_Tp* __p) noexcept
    158     {
    159       return observer_ptr<_Tp>(__p);
    160     }
    161 
    162   template<typename _Tp, typename _Up>
    163     bool
    164     operator==(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
    165     {
    166       return __p1.get() == __p2.get();
    167     }
    168 
    169   template<typename _Tp, typename _Up>
    170     bool
    171     operator!=(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
    172     {
    173     return !(__p1 == __p2);
    174     }
    175 
    176   template<typename _Tp>
    177     bool
    178     operator==(observer_ptr<_Tp> __p, nullptr_t) noexcept
    179     {
    180       return !__p;
    181     }
    182 
    183   template<typename _Tp>
    184     bool
    185     operator==(nullptr_t, observer_ptr<_Tp> __p) noexcept
    186     {
    187       return !__p;
    188     }
    189 
    190   template<typename _Tp>
    191     bool
    192     operator!=(observer_ptr<_Tp> __p, nullptr_t) noexcept
    193     {
    194       return bool(__p);
    195     }
    196 
    197   template<typename _Tp>
    198     bool
    199     operator!=(nullptr_t, observer_ptr<_Tp> __p) noexcept
    200     {
    201       return bool(__p);
    202     }
    203 
    204   template<typename _Tp, typename _Up>
    205     bool
    206     operator<(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
    207     {
    208       return std::less<typename common_type<typename add_pointer<_Tp>::type,
    209 					    typename add_pointer<_Up>::type
    210 					    >::type
    211 		       >{}(__p1.get(), __p2.get());
    212     }
    213 
    214   template<typename _Tp, typename _Up>
    215     bool
    216     operator>(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
    217     {
    218       return __p2 < __p1;
    219     }
    220 
    221   template<typename _Tp, typename _Up>
    222     bool
    223     operator<=(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
    224     {
    225       return !(__p2 < __p1);
    226     }
    227 
    228   template<typename _Tp, typename _Up>
    229     bool
    230     operator>=(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
    231     {
    232       return !(__p1 < __p2);
    233     }
    234 } // namespace fundamentals_v2
    235 } // namespace experimental
    236 
    237 template <typename _Tp>
    238   struct hash<experimental::observer_ptr<_Tp>>
    239   {
    240     using result_type = size_t;
    241     using argument_type = experimental::observer_ptr<_Tp>;
    242 
    243     size_t
    244     operator()(const experimental::observer_ptr<_Tp>& __t) const
    245     noexcept(noexcept(hash<typename add_pointer<_Tp>::type> {}(__t.get())))
    246     {
    247       return hash<typename add_pointer<_Tp>::type> {}(__t.get());
    248     }
    249   };
    250 
    251 
    252 _GLIBCXX_END_NAMESPACE_VERSION
    253 } // namespace std
    254 
    255 #endif // __cplusplus <= 201103L
    256 
    257 #endif // _GLIBCXX_EXPERIMENTAL_MEMORY
    258