From Jason Turner

[inout.ptr.t]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpzddzuq_a/{from.md → to.md} +165 -0
tmp/tmpzddzuq_a/{from.md → to.md} RENAMED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #### Class template `inout_ptr_t` <a id="inout.ptr.t">[[inout.ptr.t]]</a>
2
+
3
+ `inout_ptr_t` is a class template used to adapt types such as smart
4
+ pointers [[smartptr]] for functions that use output pointer parameters
5
+ whose dereferenced values may first be deleted before being set to
6
+ another allocated value.
7
+
8
+ [*Example 1*:
9
+
10
+ ``` cpp
11
+ #include <memory>
12
+
13
+ struct star_fish* star_fish_alloc();
14
+ int star_fish_populate(struct star_fish** ps, const char* description);
15
+
16
+ struct star_fish_deleter {
17
+ void operator() (struct star_fish* c) const noexcept;
18
+ };
19
+
20
+ using star_fish_ptr = std::unique_ptr<star_fish, star_fish_deleter>;
21
+
22
+ int main(int, char*[]) {
23
+ star_fish_ptr peach(star_fish_alloc());
24
+ // ...
25
+ // used, need to re-make
26
+ int err = star_fish_populate(std::inout_ptr(peach), "caring clown-fish liker");
27
+ return err;
28
+ }
29
+ ```
30
+
31
+ A `unique_ptr` can be used with `inout_ptr` to be passed into an output
32
+ pointer-style function. The original value will be properly deleted
33
+ according to the function it is used with and a new value reset in its
34
+ place.
35
+
36
+ — *end example*]
37
+
38
+ ``` cpp
39
+ namespace std {
40
+ template<class Smart, class Pointer, class... Args>
41
+ class inout_ptr_t {
42
+ public:
43
+ explicit inout_ptr_t(Smart&, Args...);
44
+ inout_ptr_t(const inout_ptr_t&) = delete;
45
+
46
+ ~inout_ptr_t();
47
+
48
+ operator Pointer*() const noexcept;
49
+ operator void**() const noexcept;
50
+
51
+ private:
52
+ Smart& s; // exposition only
53
+ tuple<Args...> a; // exposition only
54
+ Pointer p; // exposition only
55
+ };
56
+ }
57
+ ```
58
+
59
+ `Pointer` shall meet the *Cpp17NullablePointer* requirements. If `Smart`
60
+ is a specialization of `shared_ptr`, the program is ill-formed.
61
+
62
+ [*Note 1*: It is impossible to properly acquire unique ownership of the
63
+ managed resource from a `shared_ptr` given its shared ownership
64
+ model. — *end note*]
65
+
66
+ Program-defined specializations of `inout_ptr_t` that depend on at least
67
+ one program-defined type need not meet the requirements for the primary
68
+ template.
69
+
70
+ Evaluations of the conversion functions on the same object may conflict
71
+ [[intro.races]].
72
+
73
+ ``` cpp
74
+ explicit inout_ptr_t(Smart& smart, Args... args);
75
+ ```
76
+
77
+ *Effects:* Initializes `s` with `smart`, `a` with
78
+ `std::forward<Args>(args)...`, and `p` to either
79
+
80
+ - `smart` if `is_pointer_v<Smart>` is `true`,
81
+ - otherwise, `smart.get()`.
82
+
83
+ *Remarks:* An implementation can call `s.release()`.
84
+
85
+ [*Note 1*: The constructor is not `noexcept` to allow for a variety of
86
+ non-terminating and safe implementation strategies. For example, an
87
+ intrusive pointer implementation with a control block can allocate in
88
+ the constructor and safely fail with an exception. — *end note*]
89
+
90
+ ``` cpp
91
+ ~inout_ptr_t();
92
+ ```
93
+
94
+ Let `SP` be *`POINTER_OF_OR`*`(Smart, Pointer)` [[memory.general]].
95
+
96
+ Let *release-statement* be `s.release();` if an implementation does not
97
+ call `s.release()` in the constructor. Otherwise, it is empty.
98
+
99
+ *Effects:* Equivalent to:
100
+
101
+ -
102
+ ``` cpp
103
+ if (p) {
104
+ apply([&](auto&&... args) {
105
+ s = Smart( static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a));
106
+ }
107
+ ```
108
+
109
+ if `is_pointer_v<Smart>` is `true`;
110
+ - otherwise,
111
+ ``` cpp
112
+ release-statement;
113
+ if (p) {
114
+ apply([&](auto&&... args) {
115
+ s.reset(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a));
116
+ }
117
+ ```
118
+
119
+ if the expression
120
+ `s.reset(static_cast<SP>(p), std::forward<Args>(args)...)` is well-
121
+ formed;
122
+ - otherwise,
123
+ ``` cpp
124
+ release-statement;
125
+ if (p) {
126
+ apply([&](auto&&... args) {
127
+ s = Smart(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a));
128
+ }
129
+ ```
130
+
131
+ if `is_constructible_v<Smart, SP, Args...>` is `true`;
132
+ - otherwise, the program is ill-formed.
133
+
134
+ ``` cpp
135
+ operator Pointer*() const noexcept;
136
+ ```
137
+
138
+ *Preconditions:* `operator void**()` has not been called on `*this`.
139
+
140
+ *Returns:* `addressof(const_cast<Pointer&>(p))`.
141
+
142
+ ``` cpp
143
+ operator void**() const noexcept;
144
+ ```
145
+
146
+ *Constraints:* `is_same_v<Pointer, void*>` is `false`.
147
+
148
+ *Mandates:* `is_pointer_v<Pointer>` is `true`.
149
+
150
+ *Preconditions:* `operator Pointer*()` has not been called on `*this`.
151
+
152
+ *Returns:* A pointer value `v` such that:
153
+
154
+ - the initial value `*v` is equivalent to `static_cast<void*>(p)` and
155
+ - any modification of `*v` that is not followed by subsequent
156
+ modification of `*this` affects the value of `p` during the
157
+ destruction of `*this`, such that `static_cast<void*>(p) == *v`.
158
+
159
+ *Remarks:* Accessing `*v` outside the lifetime of `*this` has undefined
160
+ behavior.
161
+
162
+ [*Note 2*: `reinterpret_cast<void**>(static_cast<Pointer*>(*this))` can
163
+ be a viable implementation strategy for some
164
+ implementations. — *end note*]
165
+