From Jason Turner

[atomics.ref.generic]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpn6yd1nm5/{from.md → to.md} +568 -0
tmp/tmpn6yd1nm5/{from.md → to.md} RENAMED
@@ -0,0 +1,568 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Class template `atomic_ref` <a id="atomics.ref.generic">[[atomics.ref.generic]]</a>
2
+
3
+ ``` cpp
4
+ namespace std {
5
+ template<class T> struct atomic_ref {
6
+ private:
7
+ T* ptr; // exposition only
8
+ public:
9
+ using value_type = T;
10
+ static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
11
+
12
+ static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
13
+ bool is_lock_free() const noexcept;
14
+
15
+ explicit atomic_ref(T&);
16
+ atomic_ref(const atomic_ref&) noexcept;
17
+ atomic_ref& operator=(const atomic_ref&) = delete;
18
+
19
+ void store(T, memory_order = memory_order::seq_cst) const noexcept;
20
+ T operator=(T) const noexcept;
21
+ T load(memory_order = memory_order::seq_cst) const noexcept;
22
+ operator T() const noexcept;
23
+
24
+ T exchange(T, memory_order = memory_order::seq_cst) const noexcept;
25
+ bool compare_exchange_weak(T&, T,
26
+ memory_order, memory_order) const noexcept;
27
+ bool compare_exchange_strong(T&, T,
28
+ memory_order, memory_order) const noexcept;
29
+ bool compare_exchange_weak(T&, T,
30
+ memory_order = memory_order::seq_cst) const noexcept;
31
+ bool compare_exchange_strong(T&, T,
32
+ memory_order = memory_order::seq_cst) const noexcept;
33
+
34
+ void wait(T, memory_order = memory_order::seq_cst) const noexcept;
35
+ void notify_one() const noexcept;
36
+ void notify_all() const noexcept;
37
+ };
38
+ }
39
+ ```
40
+
41
+ An `atomic_ref` object applies atomic operations [[atomics.general]] to
42
+ the object referenced by `*ptr` such that, for the lifetime
43
+ [[basic.life]] of the `atomic_ref` object, the object referenced by
44
+ `*ptr` is an atomic object [[intro.races]].
45
+
46
+ The program is ill-formed if `is_trivially_copyable_v<T>` is `false`.
47
+
48
+ The lifetime [[basic.life]] of an object referenced by `*ptr` shall
49
+ exceed the lifetime of all `atomic_ref`s that reference the object.
50
+ While any `atomic_ref` instances exist that reference the `*ptr` object,
51
+ all accesses to that object shall exclusively occur through those
52
+ `atomic_ref` instances. No subobject of the object referenced by
53
+ `atomic_ref` shall be concurrently referenced by any other `atomic_ref`
54
+ object.
55
+
56
+ Atomic operations applied to an object through a referencing
57
+ `atomic_ref` are atomic with respect to atomic operations applied
58
+ through any other `atomic_ref` referencing the same object.
59
+
60
+ [*Note 1*: Atomic operations or the `atomic_ref` constructor could
61
+ acquire a shared resource, such as a lock associated with the referenced
62
+ object, to enable atomic operations to be applied to the referenced
63
+ object. — *end note*]
64
+
65
+ ### Operations <a id="atomics.ref.ops">[[atomics.ref.ops]]</a>
66
+
67
+ ``` cpp
68
+ static constexpr size_t required_alignment;
69
+ ```
70
+
71
+ The alignment required for an object to be referenced by an atomic
72
+ reference, which is at least `alignof(T)`.
73
+
74
+ [*Note 1*: Hardware could require an object referenced by an
75
+ `atomic_ref` to have stricter alignment [[basic.align]] than other
76
+ objects of type `T`. Further, whether operations on an `atomic_ref` are
77
+ lock-free could depend on the alignment of the referenced object. For
78
+ example, lock-free operations on `std::complex<double>` could be
79
+ supported only if aligned to `2*alignof(double)`. — *end note*]
80
+
81
+ ``` cpp
82
+ static constexpr bool is_always_lock_free;
83
+ ```
84
+
85
+ The static data member `is_always_lock_free` is `true` if the
86
+ `atomic_ref` type’s operations are always lock-free, and `false`
87
+ otherwise.
88
+
89
+ ``` cpp
90
+ bool is_lock_free() const noexcept;
91
+ ```
92
+
93
+ *Returns:* `true` if operations on all objects of the type
94
+ `atomic_ref<T>` are lock-free, `false` otherwise.
95
+
96
+ ``` cpp
97
+ atomic_ref(T& obj);
98
+ ```
99
+
100
+ *Preconditions:* The referenced object is aligned to
101
+ `required_alignment`.
102
+
103
+ *Ensures:* `*this` references `obj`.
104
+
105
+ *Throws:* Nothing.
106
+
107
+ ``` cpp
108
+ atomic_ref(const atomic_ref& ref) noexcept;
109
+ ```
110
+
111
+ *Ensures:* `*this` references the object referenced by `ref`.
112
+
113
+ ``` cpp
114
+ void store(T desired, memory_order order = memory_order::seq_cst) const noexcept;
115
+ ```
116
+
117
+ *Preconditions:* The `order` argument is neither
118
+ `memory_order::consume`, `memory_order::acquire`, nor
119
+ `memory_order::acq_rel`.
120
+
121
+ *Effects:* Atomically replaces the value referenced by `*ptr` with the
122
+ value of `desired`. Memory is affected according to the value of
123
+ `order`.
124
+
125
+ ``` cpp
126
+ T operator=(T desired) const noexcept;
127
+ ```
128
+
129
+ *Effects:* Equivalent to:
130
+
131
+ ``` cpp
132
+ store(desired);
133
+ return desired;
134
+ ```
135
+
136
+ ``` cpp
137
+ T load(memory_order order = memory_order::seq_cst) const noexcept;
138
+ ```
139
+
140
+ *Preconditions:* The `order` argument is neither `memory_order::release`
141
+ nor `memory_order::acq_rel`.
142
+
143
+ *Effects:* Memory is affected according to the value of `order`.
144
+
145
+ *Returns:* Atomically returns the value referenced by `*ptr`.
146
+
147
+ ``` cpp
148
+ operator T() const noexcept;
149
+ ```
150
+
151
+ *Effects:* Equivalent to: `return load();`
152
+
153
+ ``` cpp
154
+ T exchange(T desired, memory_order order = memory_order::seq_cst) const noexcept;
155
+ ```
156
+
157
+ *Effects:* Atomically replaces the value referenced by `*ptr` with
158
+ `desired`. Memory is affected according to the value of `order`. This
159
+ operation is an atomic read-modify-write
160
+ operation [[intro.multithread]].
161
+
162
+ *Returns:* Atomically returns the value referenced by `*ptr` immediately
163
+ before the effects.
164
+
165
+ ``` cpp
166
+ bool compare_exchange_weak(T& expected, T desired,
167
+ memory_order success, memory_order failure) const noexcept;
168
+
169
+ bool compare_exchange_strong(T& expected, T desired,
170
+ memory_order success, memory_order failure) const noexcept;
171
+
172
+ bool compare_exchange_weak(T& expected, T desired,
173
+ memory_order order = memory_order::seq_cst) const noexcept;
174
+
175
+ bool compare_exchange_strong(T& expected, T desired,
176
+ memory_order order = memory_order::seq_cst) const noexcept;
177
+ ```
178
+
179
+ *Preconditions:* The `failure` argument is neither
180
+ `memory_order::release` nor `memory_order::acq_rel`.
181
+
182
+ *Effects:* Retrieves the value in `expected`. It then atomically
183
+ compares the value representation of the value referenced by `*ptr` for
184
+ equality with that previously retrieved from `expected`, and if `true`,
185
+ replaces the value referenced by `*ptr` with that in `desired`. If and
186
+ only if the comparison is `true`, memory is affected according to the
187
+ value of `success`, and if the comparison is `false`, memory is affected
188
+ according to the value of `failure`. When only one `memory_order`
189
+ argument is supplied, the value of `success` is `order`, and the value
190
+ of `failure` is `order` except that a value of `memory_order::acq_rel`
191
+ shall be replaced by the value `memory_order::acquire` and a value of
192
+ `memory_order::release` shall be replaced by the value
193
+ `memory_order::relaxed`. If and only if the comparison is `false` then,
194
+ after the atomic operation, the value in `expected` is replaced by the
195
+ value read from the value referenced by `*ptr` during the atomic
196
+ comparison. If the operation returns `true`, these operations are atomic
197
+ read-modify-write operations [[intro.races]] on the value referenced by
198
+ `*ptr`. Otherwise, these operations are atomic load operations on that
199
+ memory.
200
+
201
+ *Returns:* The result of the comparison.
202
+
203
+ *Remarks:* A weak compare-and-exchange operation may fail spuriously.
204
+ That is, even when the contents of memory referred to by `expected` and
205
+ `ptr` are equal, it may return `false` and store back to `expected` the
206
+ same memory contents that were originally there.
207
+
208
+ [*Note 2*: This spurious failure enables implementation of
209
+ compare-and-exchange on a broader class of machines, e.g., load-locked
210
+ store-conditional machines. A consequence of spurious failure is that
211
+ nearly all uses of weak compare-and-exchange will be in a loop. When a
212
+ compare-and-exchange is in a loop, the weak version will yield better
213
+ performance on some platforms. When a weak compare-and-exchange would
214
+ require a loop and a strong one would not, the strong one is
215
+ preferable. — *end note*]
216
+
217
+ ``` cpp
218
+ void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
219
+ ```
220
+
221
+ *Preconditions:* `order` is neither `memory_order::release` nor
222
+ `memory_order::acq_rel`.
223
+
224
+ *Effects:* Repeatedly performs the following steps, in order:
225
+
226
+ - Evaluates `load(order)` and compares its value representation for
227
+ equality against that of `old`.
228
+ - If they compare unequal, returns.
229
+ - Blocks until it is unblocked by an atomic notifying operation or is
230
+ unblocked spuriously.
231
+
232
+ *Remarks:* This function is an atomic waiting operation [[atomics.wait]]
233
+ on atomic object `*ptr`.
234
+
235
+ ``` cpp
236
+ void notify_one() const noexcept;
237
+ ```
238
+
239
+ *Effects:* Unblocks the execution of at least one atomic waiting
240
+ operation on `*ptr` that is eligible to be unblocked [[atomics.wait]] by
241
+ this call, if any such atomic waiting operations exist.
242
+
243
+ *Remarks:* This function is an atomic notifying
244
+ operation [[atomics.wait]] on atomic object `*ptr`.
245
+
246
+ ``` cpp
247
+ void notify_all() const noexcept;
248
+ ```
249
+
250
+ *Effects:* Unblocks the execution of all atomic waiting operations on
251
+ `*ptr` that are eligible to be unblocked [[atomics.wait]] by this call.
252
+
253
+ *Remarks:* This function is an atomic notifying
254
+ operation [[atomics.wait]] on atomic object `*ptr`.
255
+
256
+ ### Specializations for integral types <a id="atomics.ref.int">[[atomics.ref.int]]</a>
257
+
258
+ There are specializations of the `atomic_ref` class template for the
259
+ integral types `char`, `signed char`, `unsigned char`, `short`,
260
+ `unsigned short`, `int`, `unsigned int`, `long`, `unsigned long`,
261
+ `long long`, `unsigned long long`, `char8_t`, `char16_t`, `char32_t`,
262
+ `wchar_t`, and any other types needed by the typedefs in the header
263
+ `<cstdint>`. For each such type `integral`, the specialization
264
+ `atomic_ref<integral>` provides additional atomic operations appropriate
265
+ to integral types.
266
+
267
+ [*Note 1*: The specialization `atomic_ref<bool>` uses the primary
268
+ template [[atomics.ref.generic]]. — *end note*]
269
+
270
+ ``` cpp
271
+ namespace std {
272
+ template<> struct atomic_ref<integral> {
273
+ private:
274
+ integral* ptr; // exposition only
275
+ public:
276
+ using value_type = integral;
277
+ using difference_type = value_type;
278
+ static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
279
+
280
+ static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
281
+ bool is_lock_free() const noexcept;
282
+
283
+ explicit atomic_ref(integral&);
284
+ atomic_ref(const atomic_ref&) noexcept;
285
+ atomic_ref& operator=(const atomic_ref&) = delete;
286
+
287
+ void store(integral, memory_order = memory_order::seq_cst) const noexcept;
288
+ integral operator=(integral) const noexcept;
289
+ integral load(memory_order = memory_order::seq_cst) const noexcept;
290
+ operator integral() const noexcept;
291
+
292
+ integral exchange(integral,
293
+ memory_order = memory_order::seq_cst) const noexcept;
294
+ bool compare_exchange_weak(integral&, integral,
295
+ memory_order, memory_order) const noexcept;
296
+ bool compare_exchange_strong(integral&, integral,
297
+ memory_order, memory_order) const noexcept;
298
+ bool compare_exchange_weak(integral&, integral,
299
+ memory_order = memory_order::seq_cst) const noexcept;
300
+ bool compare_exchange_strong(integral&, integral,
301
+ memory_order = memory_order::seq_cst) const noexcept;
302
+
303
+ integral fetch_add(integral,
304
+ memory_order = memory_order::seq_cst) const noexcept;
305
+ integral fetch_sub(integral,
306
+ memory_order = memory_order::seq_cst) const noexcept;
307
+ integral fetch_and(integral,
308
+ memory_order = memory_order::seq_cst) const noexcept;
309
+ integral fetch_or(integral,
310
+ memory_order = memory_order::seq_cst) const noexcept;
311
+ integral fetch_xor(integral,
312
+ memory_order = memory_order::seq_cst) const noexcept;
313
+
314
+ integral operator++(int) const noexcept;
315
+ integral operator--(int) const noexcept;
316
+ integral operator++() const noexcept;
317
+ integral operator--() const noexcept;
318
+ integral operator+=(integral) const noexcept;
319
+ integral operator-=(integral) const noexcept;
320
+ integral operator&=(integral) const noexcept;
321
+ integral operator|=(integral) const noexcept;
322
+ integral operator^=(integral) const noexcept;
323
+
324
+ void wait(integral, memory_order = memory_order::seq_cst) const noexcept;
325
+ void notify_one() const noexcept;
326
+ void notify_all() const noexcept;
327
+ };
328
+ }
329
+ ```
330
+
331
+ Descriptions are provided below only for members that differ from the
332
+ primary template.
333
+
334
+ The following operations perform arithmetic computations. The key,
335
+ operator, and computation correspondence is identified in
336
+ [[atomic.types.int.comp]].
337
+
338
+ ``` cpp
339
+ integral fetch_key(integral operand, memory_order order = memory_order::seq_cst) const noexcept;
340
+ ```
341
+
342
+ *Effects:* Atomically replaces the value referenced by `*ptr` with the
343
+ result of the computation applied to the value referenced by `*ptr` and
344
+ the given operand. Memory is affected according to the value of `order`.
345
+ These operations are atomic read-modify-write
346
+ operations [[intro.races]].
347
+
348
+ *Returns:* Atomically, the value referenced by `*ptr` immediately before
349
+ the effects.
350
+
351
+ *Remarks:* For signed integer types, the result is as if the object
352
+ value and parameters were converted to their corresponding unsigned
353
+ types, the computation performed on those types, and the result
354
+ converted back to the signed type.
355
+
356
+ [*Note 1*: There are no undefined results arising from the
357
+ computation. — *end note*]
358
+
359
+ ``` cpp
360
+ integral operator op=(integral operand) const noexcept;
361
+ ```
362
+
363
+ *Effects:* Equivalent to:
364
+ `return fetch_`*`key`*`(operand) `*`op`*` operand;`
365
+
366
+ ### Specializations for floating-point types <a id="atomics.ref.float">[[atomics.ref.float]]</a>
367
+
368
+ There are specializations of the `atomic_ref` class template for the
369
+ floating-point types `float`, `double`, and `long double`. For each such
370
+ type `floating-point`, the specialization `atomic_ref<floating-point>`
371
+ provides additional atomic operations appropriate to floating-point
372
+ types.
373
+
374
+ ``` cpp
375
+ namespace std {
376
+ template<> struct atomic_ref<floating-point> {
377
+ private:
378
+ floating-point* ptr; // exposition only
379
+ public:
380
+ using value_type = floating-point;
381
+ using difference_type = value_type;
382
+ static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
383
+
384
+ static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
385
+ bool is_lock_free() const noexcept;
386
+
387
+ explicit atomic_ref(floating-point&);
388
+ atomic_ref(const atomic_ref&) noexcept;
389
+ atomic_ref& operator=(const atomic_ref&) = delete;
390
+
391
+ void store(floating-point, memory_order = memory_order::seq_cst) const noexcept;
392
+ floating-point operator=(floating-point) const noexcept;
393
+ floating-point load(memory_order = memory_order::seq_cst) const noexcept;
394
+ operator floating-point() const noexcept;
395
+
396
+ floating-point exchange(floating-point,
397
+ memory_order = memory_order::seq_cst) const noexcept;
398
+ bool compare_exchange_weak(floating-point&, floating-point,
399
+ memory_order, memory_order) const noexcept;
400
+ bool compare_exchange_strong(floating-point&, floating-point,
401
+ memory_order, memory_order) const noexcept;
402
+ bool compare_exchange_weak(floating-point&, floating-point,
403
+ memory_order = memory_order::seq_cst) const noexcept;
404
+ bool compare_exchange_strong(floating-point&, floating-point,
405
+ memory_order = memory_order::seq_cst) const noexcept;
406
+
407
+ floating-point fetch_add(floating-point,
408
+ memory_order = memory_order::seq_cst) const noexcept;
409
+ floating-point fetch_sub(floating-point,
410
+ memory_order = memory_order::seq_cst) const noexcept;
411
+
412
+ floating-point operator+=(floating-point) const noexcept;
413
+ floating-point operator-=(floating-point) const noexcept;
414
+
415
+ void wait(floating-point, memory_order = memory_order::seq_cst) const noexcept;
416
+ void notify_one() const noexcept;
417
+ void notify_all() const noexcept;
418
+ };
419
+ }
420
+ ```
421
+
422
+ Descriptions are provided below only for members that differ from the
423
+ primary template.
424
+
425
+ The following operations perform arithmetic computations. The key,
426
+ operator, and computation correspondence are identified in
427
+ [[atomic.types.int.comp]].
428
+
429
+ ``` cpp
430
+ floating-point fetch_key(floating-point operand,
431
+ memory_order order = memory_order::seq_cst) const noexcept;
432
+ ```
433
+
434
+ *Effects:* Atomically replaces the value referenced by `*ptr` with the
435
+ result of the computation applied to the value referenced by `*ptr` and
436
+ the given operand. Memory is affected according to the value of `order`.
437
+ These operations are atomic read-modify-write
438
+ operations [[intro.races]].
439
+
440
+ *Returns:* Atomically, the value referenced by `*ptr` immediately before
441
+ the effects.
442
+
443
+ *Remarks:* If the result is not a representable value for its
444
+ type [[expr.pre]], the result is unspecified, but the operations
445
+ otherwise have no undefined behavior. Atomic arithmetic operations on
446
+ *`floating-point`* should conform to the
447
+ `std::numeric_limits<`*`floating-point`*`>` traits associated with the
448
+ floating-point type [[limits.syn]]. The floating-point
449
+ environment [[cfenv]] for atomic arithmetic operations on
450
+ *`floating-point`* may be different than the calling thread’s
451
+ floating-point environment.
452
+
453
+ ``` cpp
454
+ floating-point operator op=(floating-point operand) const noexcept;
455
+ ```
456
+
457
+ *Effects:* Equivalent to:
458
+ `return fetch_`*`key`*`(operand) `*`op`*` operand;`
459
+
460
+ ### Partial specialization for pointers <a id="atomics.ref.pointer">[[atomics.ref.pointer]]</a>
461
+
462
+ ``` cpp
463
+ namespace std {
464
+ template<class T> struct atomic_ref<T*> {
465
+ private:
466
+ T** ptr; // exposition only
467
+ public:
468
+ using value_type = T*;
469
+ using difference_type = ptrdiff_t;
470
+ static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
471
+
472
+ static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
473
+ bool is_lock_free() const noexcept;
474
+
475
+ explicit atomic_ref(T*&);
476
+ atomic_ref(const atomic_ref&) noexcept;
477
+ atomic_ref& operator=(const atomic_ref&) = delete;
478
+
479
+ void store(T*, memory_order = memory_order::seq_cst) const noexcept;
480
+ T* operator=(T*) const noexcept;
481
+ T* load(memory_order = memory_order::seq_cst) const noexcept;
482
+ operator T*() const noexcept;
483
+
484
+ T* exchange(T*, memory_order = memory_order::seq_cst) const noexcept;
485
+ bool compare_exchange_weak(T*&, T*,
486
+ memory_order, memory_order) const noexcept;
487
+ bool compare_exchange_strong(T*&, T*,
488
+ memory_order, memory_order) const noexcept;
489
+ bool compare_exchange_weak(T*&, T*,
490
+ memory_order = memory_order::seq_cst) const noexcept;
491
+ bool compare_exchange_strong(T*&, T*,
492
+ memory_order = memory_order::seq_cst) const noexcept;
493
+
494
+ T* fetch_add(difference_type, memory_order = memory_order::seq_cst) const noexcept;
495
+ T* fetch_sub(difference_type, memory_order = memory_order::seq_cst) const noexcept;
496
+
497
+ T* operator++(int) const noexcept;
498
+ T* operator--(int) const noexcept;
499
+ T* operator++() const noexcept;
500
+ T* operator--() const noexcept;
501
+ T* operator+=(difference_type) const noexcept;
502
+ T* operator-=(difference_type) const noexcept;
503
+
504
+ void wait(T*, memory_order = memory_order::seq_cst) const noexcept;
505
+ void notify_one() const noexcept;
506
+ void notify_all() const noexcept;
507
+ };
508
+ }
509
+ ```
510
+
511
+ Descriptions are provided below only for members that differ from the
512
+ primary template.
513
+
514
+ The following operations perform arithmetic computations. The key,
515
+ operator, and computation correspondence is identified in
516
+ [[atomic.types.pointer.comp]].
517
+
518
+ ``` cpp
519
+ T* fetch_key(difference_type operand, memory_order order = memory_order::seq_cst) const noexcept;
520
+ ```
521
+
522
+ *Mandates:* `T` is a complete object type.
523
+
524
+ *Effects:* Atomically replaces the value referenced by `*ptr` with the
525
+ result of the computation applied to the value referenced by `*ptr` and
526
+ the given operand. Memory is affected according to the value of `order`.
527
+ These operations are atomic read-modify-write
528
+ operations [[intro.races]].
529
+
530
+ *Returns:* Atomically, the value referenced by `*ptr` immediately before
531
+ the effects.
532
+
533
+ *Remarks:* The result may be an undefined address, but the operations
534
+ otherwise have no undefined behavior.
535
+
536
+ ``` cpp
537
+ T* operator op=(difference_type operand) const noexcept;
538
+ ```
539
+
540
+ *Effects:* Equivalent to:
541
+ `return fetch_`*`key`*`(operand) `*`op`*` operand;`
542
+
543
+ ### Member operators common to integers and pointers to objects <a id="atomics.ref.memop">[[atomics.ref.memop]]</a>
544
+
545
+ ``` cpp
546
+ value_type operator++(int) const noexcept;
547
+ ```
548
+
549
+ *Effects:* Equivalent to: `return fetch_add(1);`
550
+
551
+ ``` cpp
552
+ value_type operator--(int) const noexcept;
553
+ ```
554
+
555
+ *Effects:* Equivalent to: `return fetch_sub(1);`
556
+
557
+ ``` cpp
558
+ value_type operator++() const noexcept;
559
+ ```
560
+
561
+ *Effects:* Equivalent to: `return fetch_add(1) + 1;`
562
+
563
+ ``` cpp
564
+ value_type operator--() const noexcept;
565
+ ```
566
+
567
+ *Effects:* Equivalent to: `return fetch_sub(1) - 1;`
568
+