1// <experimental/memory> -*- C++ -*-
2
3// Copyright (C) 2015-2018 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 */
28
29//
30// N4336 Working Draft, C++ Extensions for Library Fundamentals, Version 2
31//
32
33#ifndef _GLIBCXX_EXPERIMENTAL_MEMORY
34#define _GLIBCXX_EXPERIMENTAL_MEMORY 1
35
36#pragma GCC system_header
37
38#if __cplusplus >= 201402L
39
40#include <memory>
41#include <type_traits>
42#include <utility>
43#include <experimental/bits/shared_ptr.h>
44#include <bits/functional_hash.h>
45
46namespace std _GLIBCXX_VISIBILITY(default)
47{
48_GLIBCXX_BEGIN_NAMESPACE_VERSION
49
50namespace experimental
51{
52inline 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
235template <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