From Jason Turner

[out.ptr.t]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpm6ygu8ga/{from.md → to.md} +165 -0
tmp/tmpm6ygu8ga/{from.md → to.md} RENAMED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #### Class template `out_ptr_t` <a id="out.ptr.t">[[out.ptr.t]]</a>
2
+
3
+ `out_ptr_t` is a class template used to adapt types such as smart
4
+ pointers [[smartptr]] for functions that use output pointer parameters.
5
+
6
+ [*Example 1*:
7
+
8
+ ``` cpp
9
+ #include <memory>
10
+ #include <cstdio>
11
+
12
+ int fopen_s(std::FILE** f, const char* name, const char* mode);
13
+
14
+ struct fclose_deleter {
15
+ void operator()(std::FILE* f) const noexcept {
16
+ std::fclose(f);
17
+ }
18
+ };
19
+
20
+ int main(int, char*[]) {
21
+ constexpr const char* file_name = "ow.o";
22
+ std::unique_ptr<std::FILE, fclose_deleter> file_ptr;
23
+ int err = fopen_s(std::out_ptr<std::FILE*>(file_ptr), file_name, "r+b");
24
+ if (err != 0)
25
+ return 1;
26
+ // *file_ptr is valid
27
+ return 0;
28
+ }
29
+ ```
30
+
31
+ `unique_ptr` can be used with `out_ptr` to be passed into an output
32
+ pointer-style function, without needing to hold onto an intermediate
33
+ pointer value and manually delete it on error or failure.
34
+
35
+ — *end example*]
36
+
37
+ ``` cpp
38
+ namespace std {
39
+ template<class Smart, class Pointer, class... Args>
40
+ class out_ptr_t {
41
+ public:
42
+ explicit out_ptr_t(Smart&, Args...);
43
+ out_ptr_t(const out_ptr_t&) = delete;
44
+
45
+ ~out_ptr_t();
46
+
47
+ operator Pointer*() const noexcept;
48
+ operator void**() const noexcept;
49
+
50
+ private:
51
+ Smart& s; // exposition only
52
+ tuple<Args...> a; // exposition only
53
+ Pointer p; // exposition only
54
+ };
55
+ }
56
+ ```
57
+
58
+ `Pointer` shall meet the *Cpp17NullablePointer* requirements. If `Smart`
59
+ is a specialization of `shared_ptr` and `sizeof...(Args) == 0`, the
60
+ program is ill-formed.
61
+
62
+ [*Note 1*: It is typically a user error to reset a `shared_ptr` without
63
+ specifying a deleter, as `shared_ptr` will replace a custom deleter upon
64
+ usage of `reset`, as specified in
65
+ [[util.smartptr.shared.mod]]. — *end note*]
66
+
67
+ Program-defined specializations of `out_ptr_t` that depend on at least
68
+ one program-defined type need not meet the requirements for the primary
69
+ template.
70
+
71
+ Evaluations of the conversion functions on the same object may conflict
72
+ [[intro.races]].
73
+
74
+ ``` cpp
75
+ explicit out_ptr_t(Smart& smart, Args... args);
76
+ ```
77
+
78
+ *Effects:* Initializes `s` with `smart`, `a` with
79
+ `std::forward<Args>(args)...`, and value-initializes `p`. Then,
80
+ equivalent to:
81
+
82
+ - ``` cpp
83
+ s.reset();
84
+ ```
85
+
86
+ if the expression `s.reset()` is well-formed;
87
+
88
+ - otherwise,
89
+ ``` cpp
90
+ s = Smart();
91
+ ```
92
+
93
+ if `is_constructible_v<Smart>` is `true`;
94
+
95
+ - otherwise, the program is ill-formed.
96
+
97
+ [*Note 1*: The constructor is not `noexcept` to allow for a variety of
98
+ non-terminating and safe implementation strategies. For example, an
99
+ implementation can allocate a `shared_ptr`’s internal node in the
100
+ constructor and let implementation-defined exceptions escape safely. The
101
+ destructor can then move the allocated control block in directly and
102
+ avoid any other exceptions. — *end note*]
103
+
104
+ ``` cpp
105
+ ~out_ptr_t();
106
+ ```
107
+
108
+ Let `SP` be *`POINTER_OF_OR`*`(Smart, Pointer)` [[memory.general]].
109
+
110
+ *Effects:* Equivalent to:
111
+
112
+ -
113
+ ``` cpp
114
+ if (p) {
115
+ apply([&](auto&&... args) {
116
+ s.reset(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a));
117
+ }
118
+ ```
119
+
120
+ if the expression
121
+ `s.reset(static_cast<SP>(p), std::forward<Args>(args)...)` is
122
+ well-formed;
123
+ - otherwise,
124
+ ``` cpp
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 a 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
+