Skip to content

Commit 7a62bee

Browse files
zoecarverldionne
andcommitted
[libc++] Implement std::experimental::observer_ptr
This patch adds std::experimental::observer_ptr (n4282) and also fixes LWG2516. Co-Authored-By: Louis Dionne <[email protected]> Differential Revision: https://reviews.llvm.org/D63230
1 parent cf7d4f5 commit 7a62bee

28 files changed

+1243
-1
lines changed

libcxx/docs/Status/Cxx17Issues.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@
143143
"`2441 <https://wg21.link/LWG2441>`__","Exact-width atomic typedefs should be provided","Oulu","|Complete|",""
144144
"`2451 <https://wg21.link/LWG2451>`__","[fund.ts.v2] optional should 'forward' T's implicit conversions","Oulu","|Nothing To Do|",""
145145
"`2509 <https://wg21.link/LWG2509>`__","[fund.ts.v2] any_cast doesn't work with rvalue reference targets and cannot move with a value target","Oulu","|Complete|",""
146-
"`2516 <https://wg21.link/LWG2516>`__","[fund.ts.v2] Public ""exposition only"" members in observer_ptr","Oulu","",""
146+
"`2516 <https://wg21.link/LWG2516>`__","[fund.ts.v2] Public ""exposition only"" members in observer_ptr","Oulu","|Complete|","18.0"
147147
"`2542 <https://wg21.link/LWG2542>`__","Missing const requirements for associative containers","Oulu","",""
148148
"`2549 <https://wg21.link/LWG2549>`__","Tuple EXPLICIT constructor templates that take tuple parameters end up taking references to temporaries and will create dangling references","Oulu","|Complete|",""
149149
"`2550 <https://wg21.link/LWG2550>`__","Wording of unordered container's clear() method complexity","Oulu","|Complete|",""

libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,7 @@ set(files
925925
experimental/iterator
926926
experimental/list
927927
experimental/map
928+
experimental/memory
928929
experimental/memory_resource
929930
experimental/propagate_const
930931
experimental/regex

libcxx/include/__std_clang_module

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
#include <experimental/iterator>
9292
#include <experimental/list>
9393
#include <experimental/map>
94+
#include <experimental/memory>
9495
#include <experimental/memory_resource>
9596
#include <experimental/propagate_const>
9697
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)

libcxx/include/experimental/memory

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef _LIBCPP_EXPERIMENTAL_MEMORY
11+
#define _LIBCPP_EXPERIMENTAL_MEMORY
12+
13+
/*
14+
experimental/memory synopsis
15+
16+
namespace std::experimental::inline fundamentals_v2 {
17+
18+
template <class W> class observer_ptr {
19+
public:
20+
using element_type = W;
21+
using pointer = add_pointer_t<W>; // exposition-only
22+
using reference = add_lvalue_reference_t<W>; // exposition-only
23+
24+
// default ctor
25+
constexpr observer_ptr() noexcept;
26+
27+
// pointer-accepting ctors
28+
constexpr observer_ptr(nullptr_t) noexcept;
29+
constexpr explicit observer_ptr(pointer) noexcept;
30+
31+
// copying ctors (in addition to compiler-generated copy ctor)
32+
template <class W2> constexpr observer_ptr(observer_ptr<W2>) noexcept;
33+
34+
// observers
35+
constexpr pointer get() const noexcept;
36+
constexpr reference operator*() const;
37+
constexpr pointer operator->() const noexcept;
38+
constexpr explicit operator bool() const noexcept;
39+
40+
// conversions
41+
constexpr explicit operator pointer() const noexcept;
42+
43+
// modifiers
44+
constexpr pointer release() noexcept;
45+
constexpr void reset(pointer = nullptr) noexcept;
46+
constexpr void swap(observer_ptr&) noexcept;
47+
};
48+
49+
}
50+
*/
51+
52+
#include <__functional/hash.h>
53+
#include <__functional/operations.h>
54+
#include <__type_traits/add_lvalue_reference.h>
55+
#include <__type_traits/add_pointer.h>
56+
#include <__type_traits/common_type.h>
57+
#include <__type_traits/enable_if.h>
58+
#include <__type_traits/is_convertible.h>
59+
#include <cstddef>
60+
#include <experimental/__config>
61+
62+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
63+
# pragma GCC system_header
64+
#endif
65+
66+
#ifdef _LIBCPP_ENABLE_EXPERIMENTAL
67+
68+
_LIBCPP_BEGIN_NAMESPACE_LFTS_V2
69+
70+
# if _LIBCPP_STD_VER >= 17
71+
72+
template <class _Wp>
73+
class observer_ptr {
74+
public:
75+
using element_type = _Wp;
76+
77+
// constructors
78+
_LIBCPP_HIDE_FROM_ABI constexpr observer_ptr() noexcept : __ptr_(nullptr) {}
79+
_LIBCPP_HIDE_FROM_ABI constexpr observer_ptr(nullptr_t) noexcept : __ptr_(nullptr) {}
80+
_LIBCPP_HIDE_FROM_ABI constexpr explicit observer_ptr(element_type* __p) noexcept : __ptr_(__p) {}
81+
82+
template <class _W2, class = __enable_if_t<is_convertible<_W2*, _Wp*>::value>>
83+
_LIBCPP_HIDE_FROM_ABI constexpr observer_ptr(observer_ptr<_W2> __other) noexcept : __ptr_(__other.get()) {}
84+
85+
// observers
86+
_LIBCPP_HIDE_FROM_ABI constexpr element_type* get() const noexcept { return __ptr_; }
87+
_LIBCPP_HIDE_FROM_ABI constexpr add_lvalue_reference_t<_Wp> operator*() const { return *__ptr_; }
88+
_LIBCPP_HIDE_FROM_ABI constexpr element_type* operator->() const noexcept { return __ptr_; }
89+
_LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __ptr_ != nullptr; }
90+
91+
// conversions
92+
_LIBCPP_HIDE_FROM_ABI constexpr explicit operator element_type*() const noexcept { return __ptr_; }
93+
94+
// modifiers
95+
_LIBCPP_HIDE_FROM_ABI constexpr void reset(element_type* __p = nullptr) noexcept { __ptr_ = __p; }
96+
_LIBCPP_HIDE_FROM_ABI constexpr void swap(observer_ptr& __other) noexcept {
97+
observer_ptr __tmp = __other;
98+
__other = *this;
99+
*this = __tmp;
100+
}
101+
_LIBCPP_HIDE_FROM_ABI constexpr element_type* release() noexcept {
102+
observer_ptr __p;
103+
__p.swap(*this);
104+
return __p.get();
105+
}
106+
107+
private:
108+
element_type* __ptr_;
109+
};
110+
111+
// specializations
112+
113+
template <class _Wp>
114+
_LIBCPP_HIDE_FROM_ABI constexpr void swap(observer_ptr<_Wp>& __a, observer_ptr<_Wp>& __b) noexcept {
115+
__a.swap(__b);
116+
}
117+
118+
template <class _Wp>
119+
_LIBCPP_HIDE_FROM_ABI observer_ptr<_Wp> make_observer(_Wp* __ptr) noexcept {
120+
return observer_ptr<_Wp>{__ptr};
121+
}
122+
123+
template <class _W1, class _W2>
124+
_LIBCPP_HIDE_FROM_ABI bool operator==(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
125+
return __a.get() == __b.get();
126+
}
127+
128+
template <class _W1, class _W2>
129+
_LIBCPP_HIDE_FROM_ABI bool operator!=(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
130+
return !(__a == __b);
131+
}
132+
133+
template <class _Wp>
134+
_LIBCPP_HIDE_FROM_ABI bool operator==(observer_ptr<_Wp> __p, nullptr_t) {
135+
return !__p;
136+
}
137+
138+
template <class _Wp>
139+
_LIBCPP_HIDE_FROM_ABI bool operator==(nullptr_t, observer_ptr<_Wp> __p) {
140+
return !__p;
141+
}
142+
143+
template <class _Wp>
144+
_LIBCPP_HIDE_FROM_ABI bool operator!=(observer_ptr<_Wp> __p, nullptr_t) {
145+
return (bool)__p;
146+
}
147+
148+
template <class _Wp>
149+
_LIBCPP_HIDE_FROM_ABI bool operator!=(nullptr_t, observer_ptr<_Wp> __p) {
150+
return (bool)__p;
151+
}
152+
153+
template <class _W1, class _W2>
154+
_LIBCPP_HIDE_FROM_ABI bool operator<(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
155+
return std::less<typename std::common_type<_W1*, _W2*>::type>()(__a.get(), __b.get());
156+
}
157+
158+
template <class _W1, class _W2>
159+
_LIBCPP_HIDE_FROM_ABI bool operator>(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
160+
return __b < __a;
161+
}
162+
163+
template <class _W1, class _W2>
164+
_LIBCPP_HIDE_FROM_ABI bool operator<=(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
165+
return !(__a > __b);
166+
}
167+
168+
template <class _W1, class _W2>
169+
_LIBCPP_HIDE_FROM_ABI bool operator>=(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
170+
return !(__a < __b);
171+
}
172+
173+
# endif // _LIBCPP_STD_VER >= 17
174+
175+
_LIBCPP_END_NAMESPACE_LFTS_V2
176+
177+
_LIBCPP_BEGIN_NAMESPACE_STD
178+
179+
// hash
180+
181+
# if _LIBCPP_STD_VER >= 17
182+
template <class _Tp>
183+
struct hash<experimental::observer_ptr<_Tp>> {
184+
_LIBCPP_HIDE_FROM_ABI size_t operator()(const experimental::observer_ptr<_Tp>& __ptr) const noexcept {
185+
return hash<_Tp*>()(__ptr.get());
186+
}
187+
};
188+
# endif // _LIBCPP_STD_VER >= 17
189+
190+
_LIBCPP_END_NAMESPACE_STD
191+
192+
#endif // _LIBCPP_ENABLE_EXPERIMENTAL
193+
194+
#endif /* _LIBCPP_EXPERIMENTAL_MEMORY */

libcxx/include/module.modulemap.in

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,10 @@ module std_experimental [system] {
533533
header "experimental/map"
534534
export *
535535
}
536+
module memory {
537+
header "experimental/memory"
538+
export *
539+
}
536540
module memory_resource {
537541
header "experimental/memory_resource"
538542
export *

libcxx/test/libcxx/transitive_includes/cxx03.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,10 @@ experimental/list experimental/memory_resource
241241
experimental/list list
242242
experimental/map experimental/memory_resource
243243
experimental/map map
244+
experimental/memory cstddef
245+
experimental/memory cstdint
246+
experimental/memory cstring
247+
experimental/memory limits
244248
experimental/memory_resource atomic
245249
experimental/memory_resource climits
246250
experimental/memory_resource concepts

libcxx/test/libcxx/transitive_includes/cxx11.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,10 @@ experimental/list experimental/memory_resource
242242
experimental/list list
243243
experimental/map experimental/memory_resource
244244
experimental/map map
245+
experimental/memory cstddef
246+
experimental/memory cstdint
247+
experimental/memory cstring
248+
experimental/memory limits
245249
experimental/memory_resource atomic
246250
experimental/memory_resource climits
247251
experimental/memory_resource concepts

libcxx/test/libcxx/transitive_includes/cxx14.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,10 @@ experimental/list experimental/memory_resource
242242
experimental/list list
243243
experimental/map experimental/memory_resource
244244
experimental/map map
245+
experimental/memory cstddef
246+
experimental/memory cstdint
247+
experimental/memory cstring
248+
experimental/memory limits
245249
experimental/memory_resource atomic
246250
experimental/memory_resource climits
247251
experimental/memory_resource concepts

libcxx/test/libcxx/transitive_includes/cxx17.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,10 @@ experimental/list experimental/memory_resource
242242
experimental/list list
243243
experimental/map experimental/memory_resource
244244
experimental/map map
245+
experimental/memory cstddef
246+
experimental/memory cstdint
247+
experimental/memory cstring
248+
experimental/memory limits
245249
experimental/memory_resource atomic
246250
experimental/memory_resource climits
247251
experimental/memory_resource concepts

libcxx/test/libcxx/transitive_includes/cxx20.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,10 @@ experimental/list experimental/memory_resource
248248
experimental/list list
249249
experimental/map experimental/memory_resource
250250
experimental/map map
251+
experimental/memory cstddef
252+
experimental/memory cstdint
253+
experimental/memory cstring
254+
experimental/memory limits
251255
experimental/memory_resource atomic
252256
experimental/memory_resource climits
253257
experimental/memory_resource concepts

libcxx/test/libcxx/transitive_includes/cxx23.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ experimental/list experimental/memory_resource
170170
experimental/list list
171171
experimental/map experimental/memory_resource
172172
experimental/map map
173+
experimental/memory cstddef
174+
experimental/memory cstdint
175+
experimental/memory cstring
176+
experimental/memory limits
173177
experimental/memory_resource cstddef
174178
experimental/memory_resource experimental/utility
175179
experimental/memory_resource limits

libcxx/test/libcxx/transitive_includes/cxx26.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ experimental/list experimental/memory_resource
170170
experimental/list list
171171
experimental/map experimental/memory_resource
172172
experimental/map map
173+
experimental/memory cstddef
174+
experimental/memory cstdint
175+
experimental/memory cstring
176+
experimental/memory limits
173177
experimental/memory_resource cstddef
174178
experimental/memory_resource experimental/utility
175179
experimental/memory_resource limits

0 commit comments

Comments
 (0)