From Jason Turner

[atomics.types.generic]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpb5w6lx58/{from.md → to.md} +482 -197
tmp/tmpb5w6lx58/{from.md → to.md} RENAMED
@@ -17,35 +17,35 @@ namespace std {
17
  atomic(const atomic&) = delete;
18
  atomic& operator=(const atomic&) = delete;
19
  atomic& operator=(const atomic&) volatile = delete;
20
 
21
  T load(memory_order = memory_order::seq_cst) const volatile noexcept;
22
- T load(memory_order = memory_order::seq_cst) const noexcept;
23
  operator T() const volatile noexcept;
24
- operator T() const noexcept;
25
  void store(T, memory_order = memory_order::seq_cst) volatile noexcept;
26
- void store(T, memory_order = memory_order::seq_cst) noexcept;
27
  T operator=(T) volatile noexcept;
28
- T operator=(T) noexcept;
29
 
30
  T exchange(T, memory_order = memory_order::seq_cst) volatile noexcept;
31
- T exchange(T, memory_order = memory_order::seq_cst) noexcept;
32
  bool compare_exchange_weak(T&, T, memory_order, memory_order) volatile noexcept;
33
- bool compare_exchange_weak(T&, T, memory_order, memory_order) noexcept;
34
  bool compare_exchange_strong(T&, T, memory_order, memory_order) volatile noexcept;
35
- bool compare_exchange_strong(T&, T, memory_order, memory_order) noexcept;
36
  bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) volatile noexcept;
37
- bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) noexcept;
38
  bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) volatile noexcept;
39
- bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) noexcept;
40
 
41
  void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept;
42
- void wait(T, memory_order = memory_order::seq_cst) const noexcept;
43
  void notify_one() volatile noexcept;
44
- void notify_one() noexcept;
45
  void notify_all() volatile noexcept;
46
- void notify_all() noexcept;
47
  };
48
  }
49
  ```
50
 
51
  The template argument for `T` shall meet the *Cpp17CopyConstructible*
@@ -53,19 +53,21 @@ and *Cpp17CopyAssignable* requirements. The program is ill-formed if any
53
  of
54
 
55
  - `is_trivially_copyable_v<T>`,
56
  - `is_copy_constructible_v<T>`,
57
  - `is_move_constructible_v<T>`,
58
- - `is_copy_assignable_v<T>`, or
59
- - `is_move_assignable_v<T>`
 
60
 
61
  is `false`.
62
 
63
  [*Note 1*: Type arguments that are not also statically initializable
64
  can be difficult to use. — *end note*]
65
 
66
- The specialization `atomic<bool>` is a standard-layout struct.
 
67
 
68
  [*Note 2*: The representation of an atomic specialization need not have
69
  the same size and alignment requirement as its corresponding argument
70
  type. — *end note*]
71
 
@@ -73,11 +75,11 @@ type. — *end note*]
73
 
74
  ``` cpp
75
  constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>);
76
  ```
77
 
78
- *Mandates:* `is_default_constructible_v<T>` is `true`.
79
 
80
  *Effects:* Initializes the atomic object with the value of `T()`.
81
  Initialization is not an atomic operation [[intro.multithread]].
82
 
83
  ``` cpp
@@ -117,27 +119,26 @@ otherwise.
117
  consistent with the value of `is_always_lock_free` for the same
118
  type. — *end note*]
119
 
120
  ``` cpp
121
  void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
122
- void store(T desired, memory_order order = memory_order::seq_cst) noexcept;
123
  ```
124
 
125
  *Constraints:* For the `volatile` overload of this function,
126
  `is_always_lock_free` is `true`.
127
 
128
- *Preconditions:* The `order` argument is neither
129
- `memory_order::consume`, `memory_order::acquire`, nor
130
- `memory_order::acq_rel`.
131
 
132
  *Effects:* Atomically replaces the value pointed to by `this` with the
133
  value of `desired`. Memory is affected according to the value of
134
  `order`.
135
 
136
  ``` cpp
137
  T operator=(T desired) volatile noexcept;
138
- T operator=(T desired) noexcept;
139
  ```
140
 
141
  *Constraints:* For the `volatile` overload of this function,
142
  `is_always_lock_free` is `true`.
143
 
@@ -145,36 +146,36 @@ T operator=(T desired) noexcept;
145
 
146
  *Returns:* `desired`.
147
 
148
  ``` cpp
149
  T load(memory_order order = memory_order::seq_cst) const volatile noexcept;
150
- T load(memory_order order = memory_order::seq_cst) const noexcept;
151
  ```
152
 
153
  *Constraints:* For the `volatile` overload of this function,
154
  `is_always_lock_free` is `true`.
155
 
156
- *Preconditions:* The `order` argument is neither `memory_order::release`
157
- nor `memory_order::acq_rel`.
158
 
159
  *Effects:* Memory is affected according to the value of `order`.
160
 
161
  *Returns:* Atomically returns the value pointed to by `this`.
162
 
163
  ``` cpp
164
  operator T() const volatile noexcept;
165
- operator T() const noexcept;
166
  ```
167
 
168
  *Constraints:* For the `volatile` overload of this function,
169
  `is_always_lock_free` is `true`.
170
 
171
  *Effects:* Equivalent to: `return load();`
172
 
173
  ``` cpp
174
  T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
175
- T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept;
176
  ```
177
 
178
  *Constraints:* For the `volatile` overload of this function,
179
  `is_always_lock_free` is `true`.
180
 
@@ -187,31 +188,31 @@ operations [[intro.multithread]].
187
  before the effects.
188
 
189
  ``` cpp
190
  bool compare_exchange_weak(T& expected, T desired,
191
  memory_order success, memory_order failure) volatile noexcept;
192
- bool compare_exchange_weak(T& expected, T desired,
193
  memory_order success, memory_order failure) noexcept;
194
  bool compare_exchange_strong(T& expected, T desired,
195
  memory_order success, memory_order failure) volatile noexcept;
196
- bool compare_exchange_strong(T& expected, T desired,
197
  memory_order success, memory_order failure) noexcept;
198
  bool compare_exchange_weak(T& expected, T desired,
199
  memory_order order = memory_order::seq_cst) volatile noexcept;
200
- bool compare_exchange_weak(T& expected, T desired,
201
  memory_order order = memory_order::seq_cst) noexcept;
202
  bool compare_exchange_strong(T& expected, T desired,
203
  memory_order order = memory_order::seq_cst) volatile noexcept;
204
- bool compare_exchange_strong(T& expected, T desired,
205
  memory_order order = memory_order::seq_cst) noexcept;
206
  ```
207
 
208
  *Constraints:* For the `volatile` overload of this function,
209
  `is_always_lock_free` is `true`.
210
 
211
- *Preconditions:* The `failure` argument is neither
212
- `memory_order::release` nor `memory_order::acq_rel`.
213
 
214
  *Effects:* Retrieves the value in `expected`. It then atomically
215
  compares the value representation of the value pointed to by `this` for
216
  equality with that previously retrieved from `expected`, and if true,
217
  replaces the value pointed to by `this` with that in `desired`. If and
@@ -296,14 +297,14 @@ preferable. — *end note*]
296
 
297
  [*Note 6*: Under cases where the `memcpy` and `memcmp` semantics of the
298
  compare-and-exchange operations apply, the comparisons can fail for
299
  values that compare equal with `operator==` if the value representation
300
  has trap bits or alternate representations of the same value. Notably,
301
- on implementations conforming to ISO/IEC/IEEE 60559, floating-point
302
- `-0.0` and `+0.0` will not compare equal with `memcmp` but will compare
303
- equal with `operator==`, and NaNs with the same payload will compare
304
- equal with `memcmp` but will not compare equal with
305
  `operator==`. — *end note*]
306
 
307
  [*Note 7*:
308
 
309
  Because compare-and-exchange acts on an object’s value representation,
@@ -350,15 +351,15 @@ bool party(pony desired) {
350
 
351
  — *end note*]
352
 
353
  ``` cpp
354
  void wait(T old, memory_order order = memory_order::seq_cst) const volatile noexcept;
355
- void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
356
  ```
357
 
358
- *Preconditions:* `order` is neither `memory_order::release` nor
359
- `memory_order::acq_rel`.
360
 
361
  *Effects:* Repeatedly performs the following steps, in order:
362
 
363
  - Evaluates `load(order)` and compares its value representation for
364
  equality against that of `old`.
@@ -369,11 +370,11 @@ void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
369
  *Remarks:* This function is an atomic waiting
370
  operation [[atomics.wait]].
371
 
372
  ``` cpp
373
  void notify_one() volatile noexcept;
374
- void notify_one() noexcept;
375
  ```
376
 
377
  *Effects:* Unblocks the execution of at least one atomic waiting
378
  operation that is eligible to be unblocked [[atomics.wait]] by this
379
  call, if any such atomic waiting operations exist.
@@ -381,11 +382,11 @@ call, if any such atomic waiting operations exist.
381
  *Remarks:* This function is an atomic notifying
382
  operation [[atomics.wait]].
383
 
384
  ``` cpp
385
  void notify_all() volatile noexcept;
386
- void notify_all() noexcept;
387
  ```
388
 
389
  *Effects:* Unblocks the execution of all atomic waiting operations that
390
  are eligible to be unblocked [[atomics.wait]] by this call.
391
 
@@ -421,85 +422,122 @@ namespace std {
421
  atomic(const atomic&) = delete;
422
  atomic& operator=(const atomic&) = delete;
423
  atomic& operator=(const atomic&) volatile = delete;
424
 
425
  void store(integral-type, memory_order = memory_order::seq_cst) volatile noexcept;
426
- void store(integral-type, memory_order = memory_order::seq_cst) noexcept;
427
  integral-type operator=(integral-type) volatile noexcept;
428
- integral-type operator=(integral-type) noexcept;
429
  integral-type load(memory_order = memory_order::seq_cst) const volatile noexcept;
430
- integral-type load(memory_order = memory_order::seq_cst) const noexcept;
431
  operator integral-type() const volatile noexcept;
432
- operator integral-type() const noexcept;
433
 
434
  integral-type exchange(integral-type,
435
  memory_order = memory_order::seq_cst) volatile noexcept;
436
- integral-type exchange(integral-type,
437
  memory_order = memory_order::seq_cst) noexcept;
438
  bool compare_exchange_weak(integral-type&, integral-type,
439
  memory_order, memory_order) volatile noexcept;
440
- bool compare_exchange_weak(integral-type&, integral-type,
441
  memory_order, memory_order) noexcept;
442
  bool compare_exchange_strong(integral-type&, integral-type,
443
  memory_order, memory_order) volatile noexcept;
444
- bool compare_exchange_strong(integral-type&, integral-type,
445
  memory_order, memory_order) noexcept;
446
  bool compare_exchange_weak(integral-type&, integral-type,
447
  memory_order = memory_order::seq_cst) volatile noexcept;
448
- bool compare_exchange_weak(integral-type&, integral-type,
449
  memory_order = memory_order::seq_cst) noexcept;
450
  bool compare_exchange_strong(integral-type&, integral-type,
451
  memory_order = memory_order::seq_cst) volatile noexcept;
452
- bool compare_exchange_strong(integral-type&, integral-type,
453
  memory_order = memory_order::seq_cst) noexcept;
454
 
455
  integral-type fetch_add(integral-type,
456
  memory_order = memory_order::seq_cst) volatile noexcept;
457
- integral-type fetch_add(integral-type,
458
  memory_order = memory_order::seq_cst) noexcept;
459
  integral-type fetch_sub(integral-type,
460
  memory_order = memory_order::seq_cst) volatile noexcept;
461
- integral-type fetch_sub(integral-type,
462
  memory_order = memory_order::seq_cst) noexcept;
463
  integral-type fetch_and(integral-type,
464
  memory_order = memory_order::seq_cst) volatile noexcept;
465
- integral-type fetch_and(integral-type,
466
  memory_order = memory_order::seq_cst) noexcept;
467
  integral-type fetch_or(integral-type,
468
  memory_order = memory_order::seq_cst) volatile noexcept;
469
- integral-type fetch_or(integral-type,
470
  memory_order = memory_order::seq_cst) noexcept;
471
  integral-type fetch_xor(integral-type,
472
  memory_order = memory_order::seq_cst) volatile noexcept;
473
- integral-type fetch_xor(integral-type,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
474
  memory_order = memory_order::seq_cst) noexcept;
475
 
476
  integral-type operator++(int) volatile noexcept;
477
- integral-type operator++(int) noexcept;
478
  integral-type operator--(int) volatile noexcept;
479
- integral-type operator--(int) noexcept;
480
  integral-type operator++() volatile noexcept;
481
- integral-type operator++() noexcept;
482
  integral-type operator--() volatile noexcept;
483
- integral-type operator--() noexcept;
484
  integral-type operator+=(integral-type) volatile noexcept;
485
- integral-type operator+=(integral-type) noexcept;
486
  integral-type operator-=(integral-type) volatile noexcept;
487
- integral-type operator-=(integral-type) noexcept;
488
  integral-type operator&=(integral-type) volatile noexcept;
489
- integral-type operator&=(integral-type) noexcept;
490
  integral-type operator|=(integral-type) volatile noexcept;
491
- integral-type operator|=(integral-type) noexcept;
492
  integral-type operator^=(integral-type) volatile noexcept;
493
- integral-type operator^=(integral-type) noexcept;
494
 
495
  void wait(integral-type, memory_order = memory_order::seq_cst) const volatile noexcept;
496
- void wait(integral-type, memory_order = memory_order::seq_cst) const noexcept;
497
  void notify_one() volatile noexcept;
498
- void notify_one() noexcept;
499
  void notify_all() volatile noexcept;
500
- void notify_all() noexcept;
501
  };
502
  }
503
  ```
504
 
505
  The atomic integral specializations are standard-layout structs. They
@@ -513,18 +551,21 @@ correspondence among key, operator, and computation is specified in
513
  [[atomic.types.int.comp]].
514
 
515
  **Table: Atomic arithmetic computations** <a id="atomic.types.int.comp">[atomic.types.int.comp]</a>
516
 
517
  | | | | | | |
518
- | ----- | --- | -------------------- | ----- | --- | -------------------- |
519
- | `add` | `+` | addition | `sub` | `-` | subtraction |
520
- | `or` | `|` | bitwise inclusive or | `xor` | `^` | bitwise exclusive or |
521
- | `and` | `&` | bitwise and | | | |
 
522
 
523
  ``` cpp
524
- T fetch_key(T operand, memory_order order = memory_order::seq_cst) volatile noexcept;
525
- T fetch_key(T operand, memory_order order = memory_order::seq_cst) noexcept;
 
 
526
  ```
527
 
528
  *Constraints:* For the `volatile` overload of this function,
529
  `is_always_lock_free` is `true`.
530
 
@@ -535,21 +576,59 @@ the given `operand`. Memory is affected according to the value of
535
  operations [[intro.multithread]].
536
 
537
  *Returns:* Atomically, the value pointed to by `this` immediately before
538
  the effects.
539
 
540
- *Remarks:* For signed integer types, the result is as if the object
541
- value and parameters were converted to their corresponding unsigned
542
- types, the computation performed on those types, and the result
543
- converted back to the signed type.
544
 
545
  [*Note 1*: There are no undefined results arising from the
546
  computation. — *end note*]
547
 
 
 
 
 
 
548
  ``` cpp
549
- T operator op=(T operand) volatile noexcept;
550
- T operator op=(T operand) noexcept;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
551
  ```
552
 
553
  *Constraints:* For the `volatile` overload of this function,
554
  `is_always_lock_free` is `true`.
555
 
@@ -579,59 +658,117 @@ namespace std {
579
  atomic(const atomic&) = delete;
580
  atomic& operator=(const atomic&) = delete;
581
  atomic& operator=(const atomic&) volatile = delete;
582
 
583
  void store(floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept;
584
- void store(floating-point-type, memory_order = memory_order::seq_cst) noexcept;
585
  floating-point-type operator=(floating-point-type) volatile noexcept;
586
- floating-point-type operator=(floating-point-type) noexcept;
587
  floating-point-type load(memory_order = memory_order::seq_cst) volatile noexcept;
588
- floating-point-type load(memory_order = memory_order::seq_cst) noexcept;
589
  operator floating-point-type() volatile noexcept;
590
- operator floating-point-type() noexcept;
591
 
592
  floating-point-type exchange(floating-point-type,
593
  memory_order = memory_order::seq_cst) volatile noexcept;
594
- floating-point-type exchange(floating-point-type,
595
  memory_order = memory_order::seq_cst) noexcept;
596
  bool compare_exchange_weak(floating-point-type&, floating-point-type,
597
  memory_order, memory_order) volatile noexcept;
598
- bool compare_exchange_weak(floating-point-type&, floating-point-type,
599
  memory_order, memory_order) noexcept;
600
  bool compare_exchange_strong(floating-point-type&, floating-point-type,
601
  memory_order, memory_order) volatile noexcept;
602
- bool compare_exchange_strong(floating-point-type&, floating-point-type,
603
  memory_order, memory_order) noexcept;
604
  bool compare_exchange_weak(floating-point-type&, floating-point-type,
605
  memory_order = memory_order::seq_cst) volatile noexcept;
606
- bool compare_exchange_weak(floating-point-type&, floating-point-type,
607
  memory_order = memory_order::seq_cst) noexcept;
608
  bool compare_exchange_strong(floating-point-type&, floating-point-type,
609
  memory_order = memory_order::seq_cst) volatile noexcept;
610
- bool compare_exchange_strong(floating-point-type&, floating-point-type,
611
  memory_order = memory_order::seq_cst) noexcept;
612
 
613
  floating-point-type fetch_add(floating-point-type,
614
  memory_order = memory_order::seq_cst) volatile noexcept;
615
- floating-point-type fetch_add(floating-point-type,
616
  memory_order = memory_order::seq_cst) noexcept;
617
  floating-point-type fetch_sub(floating-point-type,
618
  memory_order = memory_order::seq_cst) volatile noexcept;
619
- floating-point-type fetch_sub(floating-point-type,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
620
  memory_order = memory_order::seq_cst) noexcept;
621
 
622
  floating-point-type operator+=(floating-point-type) volatile noexcept;
623
- floating-point-type operator+=(floating-point-type) noexcept;
624
  floating-point-type operator-=(floating-point-type) volatile noexcept;
625
- floating-point-type operator-=(floating-point-type) noexcept;
626
 
627
  void wait(floating-point-type, memory_order = memory_order::seq_cst) const volatile noexcept;
628
- void wait(floating-point-type, memory_order = memory_order::seq_cst) const noexcept;
 
629
  void notify_one() volatile noexcept;
630
- void notify_one() noexcept;
631
  void notify_all() volatile noexcept;
632
- void notify_all() noexcept;
633
  };
634
  }
635
  ```
636
 
637
  The atomic floating-point specializations are standard-layout structs.
@@ -640,15 +777,19 @@ They each have a trivial destructor.
640
  Descriptions are provided below only for members that differ from the
641
  primary template.
642
 
643
  The following operations perform arithmetic addition and subtraction
644
  computations. The correspondence among key, operator, and computation is
645
- specified in [[atomic.types.int.comp]].
 
 
646
 
647
  ``` cpp
648
- T fetch_key(T operand, memory_order order = memory_order::seq_cst) volatile noexcept;
649
- T fetch_key(T operand, memory_order order = memory_order::seq_cst) noexcept;
 
 
650
  ```
651
 
652
  *Constraints:* For the `volatile` overload of this function,
653
  `is_always_lock_free` is `true`.
654
 
@@ -669,13 +810,92 @@ otherwise have no undefined behavior. Atomic arithmetic operations on
669
  the floating-point type [[limits.syn]]. The floating-point
670
  environment [[cfenv]] for atomic arithmetic operations on
671
  *`floating-point-type`* may be different than the calling thread’s
672
  floating-point environment.
673
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
674
  ``` cpp
675
- T operator op=(T operand) volatile noexcept;
676
- T operator op=(T operand) noexcept;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
677
  ```
678
 
679
  *Constraints:* For the `volatile` overload of this function,
680
  `is_always_lock_free` is `true`.
681
 
@@ -709,57 +929,70 @@ namespace std {
709
  atomic(const atomic&) = delete;
710
  atomic& operator=(const atomic&) = delete;
711
  atomic& operator=(const atomic&) volatile = delete;
712
 
713
  void store(T*, memory_order = memory_order::seq_cst) volatile noexcept;
714
- void store(T*, memory_order = memory_order::seq_cst) noexcept;
715
  T* operator=(T*) volatile noexcept;
716
- T* operator=(T*) noexcept;
717
  T* load(memory_order = memory_order::seq_cst) const volatile noexcept;
718
- T* load(memory_order = memory_order::seq_cst) const noexcept;
719
  operator T*() const volatile noexcept;
720
- operator T*() const noexcept;
721
 
722
  T* exchange(T*, memory_order = memory_order::seq_cst) volatile noexcept;
723
- T* exchange(T*, memory_order = memory_order::seq_cst) noexcept;
724
  bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile noexcept;
725
- bool compare_exchange_weak(T*&, T*, memory_order, memory_order) noexcept;
726
  bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile noexcept;
727
- bool compare_exchange_strong(T*&, T*, memory_order, memory_order) noexcept;
728
  bool compare_exchange_weak(T*&, T*,
729
  memory_order = memory_order::seq_cst) volatile noexcept;
730
- bool compare_exchange_weak(T*&, T*,
731
  memory_order = memory_order::seq_cst) noexcept;
732
  bool compare_exchange_strong(T*&, T*,
733
  memory_order = memory_order::seq_cst) volatile noexcept;
734
- bool compare_exchange_strong(T*&, T*,
735
  memory_order = memory_order::seq_cst) noexcept;
736
 
737
  T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
738
- T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
739
  T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
740
- T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
 
 
 
 
 
 
 
 
 
 
 
 
 
741
 
742
  T* operator++(int) volatile noexcept;
743
- T* operator++(int) noexcept;
744
  T* operator--(int) volatile noexcept;
745
- T* operator--(int) noexcept;
746
  T* operator++() volatile noexcept;
747
- T* operator++() noexcept;
748
  T* operator--() volatile noexcept;
749
- T* operator--() noexcept;
750
  T* operator+=(ptrdiff_t) volatile noexcept;
751
- T* operator+=(ptrdiff_t) noexcept;
752
  T* operator-=(ptrdiff_t) volatile noexcept;
753
- T* operator-=(ptrdiff_t) noexcept;
754
 
755
  void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept;
756
- void wait(T*, memory_order = memory_order::seq_cst) const noexcept;
757
  void notify_one() volatile noexcept;
758
- void notify_one() noexcept;
759
  void notify_all() volatile noexcept;
760
- void notify_all() noexcept;
761
  };
762
  }
763
  ```
764
 
765
  There is a partial specialization of the `atomic` class template for
@@ -776,14 +1009,15 @@ among key, operator, and computation is specified in
776
  **Table: Atomic pointer computations** <a id="atomic.types.pointer.comp">[atomic.types.pointer.comp]</a>
777
 
778
  | | | | | | |
779
  | ----- | --- | -------- | ----- | --- | ----------- |
780
  | `add` | `+` | addition | `sub` | `-` | subtraction |
 
781
 
782
  ``` cpp
783
- T* fetch_key(ptrdiff_t operand, memory_order order = memory_order::seq_cst) volatile noexcept;
784
- T* fetch_key(ptrdiff_t operand, memory_order order = memory_order::seq_cst) noexcept;
785
  ```
786
 
787
  *Constraints:* For the `volatile` overload of this function,
788
  `is_always_lock_free` is `true`.
789
 
@@ -802,13 +1036,51 @@ operations [[intro.multithread]].
802
  the effects.
803
 
804
  *Remarks:* The result may be an undefined address, but the operations
805
  otherwise have no undefined behavior.
806
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
807
  ``` cpp
808
  T* operator op=(ptrdiff_t operand) volatile noexcept;
809
- T* operator op=(ptrdiff_t operand) noexcept;
810
  ```
811
 
812
  *Constraints:* For the `volatile` overload of this function,
813
  `is_always_lock_free` is `true`.
814
 
@@ -817,41 +1089,41 @@ T* operator op=(ptrdiff_t operand) noexcept;
817
 
818
  #### Member operators common to integers and pointers to objects <a id="atomics.types.memop">[[atomics.types.memop]]</a>
819
 
820
  ``` cpp
821
  value_type operator++(int) volatile noexcept;
822
- value_type operator++(int) noexcept;
823
  ```
824
 
825
  *Constraints:* For the `volatile` overload of this function,
826
  `is_always_lock_free` is `true`.
827
 
828
  *Effects:* Equivalent to: `return fetch_add(1);`
829
 
830
  ``` cpp
831
  value_type operator--(int) volatile noexcept;
832
- value_type operator--(int) noexcept;
833
  ```
834
 
835
  *Constraints:* For the `volatile` overload of this function,
836
  `is_always_lock_free` is `true`.
837
 
838
  *Effects:* Equivalent to: `return fetch_sub(1);`
839
 
840
  ``` cpp
841
  value_type operator++() volatile noexcept;
842
- value_type operator++() noexcept;
843
  ```
844
 
845
  *Constraints:* For the `volatile` overload of this function,
846
  `is_always_lock_free` is `true`.
847
 
848
  *Effects:* Equivalent to: `return fetch_add(1) + 1;`
849
 
850
  ``` cpp
851
  value_type operator--() volatile noexcept;
852
- value_type operator--() noexcept;
853
  ```
854
 
855
  *Constraints:* For the `volatile` overload of this function,
856
  `is_always_lock_free` is `true`.
857
 
@@ -924,33 +1196,36 @@ namespace std {
924
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
925
  bool is_lock_free() const noexcept;
926
 
927
  constexpr atomic() noexcept;
928
  constexpr atomic(nullptr_t) noexcept : atomic() { }
929
- atomic(shared_ptr<T> desired) noexcept;
930
  atomic(const atomic&) = delete;
931
  void operator=(const atomic&) = delete;
932
 
933
- shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
934
- operator shared_ptr<T>() const noexcept;
935
- void store(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
936
- void operator=(shared_ptr<T> desired) noexcept;
 
 
937
 
938
- shared_ptr<T> exchange(shared_ptr<T> desired,
939
  memory_order order = memory_order::seq_cst) noexcept;
940
- bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
941
  memory_order success, memory_order failure) noexcept;
942
- bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
943
  memory_order success, memory_order failure) noexcept;
944
- bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
945
  memory_order order = memory_order::seq_cst) noexcept;
946
- bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
947
  memory_order order = memory_order::seq_cst) noexcept;
948
 
949
- void wait(shared_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
950
- void notify_one() noexcept;
951
- void notify_all() noexcept;
 
952
 
953
  private:
954
  shared_ptr<T> p; // exposition only
955
  };
956
  }
@@ -958,14 +1233,14 @@ namespace std {
958
 
959
  ``` cpp
960
  constexpr atomic() noexcept;
961
  ```
962
 
963
- *Effects:* Initializes `p{}`.
964
 
965
  ``` cpp
966
- atomic(shared_ptr<T> desired) noexcept;
967
  ```
968
 
969
  *Effects:* Initializes the object with the value `desired`.
970
  Initialization is not an atomic operation [[intro.multithread]].
971
 
@@ -975,63 +1250,70 @@ the just-constructed object `A` to another thread via
975
  `memory_order::relaxed` operations on a suitable atomic pointer
976
  variable, and then immediately accessing `A` in the receiving thread.
977
  This results in undefined behavior. — *end note*]
978
 
979
  ``` cpp
980
- void store(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
981
  ```
982
 
983
- *Preconditions:* `order` is neither `memory_order::consume`,
984
- `memory_order::acquire`, nor `memory_order::acq_rel`.
985
 
986
  *Effects:* Atomically replaces the value pointed to by `this` with the
987
  value of `desired` as if by `p.swap(desired)`. Memory is affected
988
  according to the value of `order`.
989
 
990
  ``` cpp
991
- void operator=(shared_ptr<T> desired) noexcept;
992
  ```
993
 
994
  *Effects:* Equivalent to `store(desired)`.
995
 
996
  ``` cpp
997
- shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
998
  ```
999
 
1000
- *Preconditions:* `order` is neither `memory_order::release` nor
1001
- `memory_order::acq_rel`.
 
 
 
 
 
 
1002
 
1003
  *Effects:* Memory is affected according to the value of `order`.
1004
 
1005
  *Returns:* Atomically returns `p`.
1006
 
1007
  ``` cpp
1008
- operator shared_ptr<T>() const noexcept;
1009
  ```
1010
 
1011
  *Effects:* Equivalent to: `return load();`
1012
 
1013
  ``` cpp
1014
- shared_ptr<T> exchange(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
 
1015
  ```
1016
 
1017
  *Effects:* Atomically replaces `p` with `desired` as if by
1018
  `p.swap(desired)`. Memory is affected according to the value of `order`.
1019
  This is an atomic read-modify-write operation [[intro.races]].
1020
 
1021
  *Returns:* Atomically returns the value of `p` immediately before the
1022
  effects.
1023
 
1024
  ``` cpp
1025
- bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
1026
  memory_order success, memory_order failure) noexcept;
1027
- bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
1028
  memory_order success, memory_order failure) noexcept;
1029
  ```
1030
 
1031
- *Preconditions:* `failure` is neither `memory_order::release` nor
1032
- `memory_order::acq_rel`.
1033
 
1034
  *Effects:* If `p` is equivalent to `expected`, assigns `desired` to `p`
1035
  and has synchronization semantics corresponding to the value of
1036
  `success`, otherwise assigns `p` to `expected` and has synchronization
1037
  semantics corresponding to the value of `failure`.
@@ -1052,11 +1334,11 @@ object in the attempted atomic update. The `use_count` update
1052
  corresponding to the write to `expected` is part of the atomic
1053
  operation. The write to `expected` itself is not required to be part of
1054
  the atomic operation.
1055
 
1056
  ``` cpp
1057
- bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
1058
  memory_order order = memory_order::seq_cst) noexcept;
1059
  ```
1060
 
1061
  *Effects:* Equivalent to:
1062
 
@@ -1068,11 +1350,11 @@ where `fail_order` is the same as `order` except that a value of
1068
  `memory_order::acq_rel` shall be replaced by the value
1069
  `memory_order::acquire` and a value of `memory_order::release` shall be
1070
  replaced by the value `memory_order::relaxed`.
1071
 
1072
  ``` cpp
1073
- bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
1074
  memory_order order = memory_order::seq_cst) noexcept;
1075
  ```
1076
 
1077
  *Effects:* Equivalent to:
1078
 
@@ -1084,15 +1366,15 @@ where `fail_order` is the same as `order` except that a value of
1084
  `memory_order::acq_rel` shall be replaced by the value
1085
  `memory_order::acquire` and a value of `memory_order::release` shall be
1086
  replaced by the value `memory_order::relaxed`.
1087
 
1088
  ``` cpp
1089
- void wait(shared_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
1090
  ```
1091
 
1092
- *Preconditions:* `order` is neither `memory_order::release` nor
1093
- `memory_order::acq_rel`.
1094
 
1095
  *Effects:* Repeatedly performs the following steps, in order:
1096
 
1097
  - Evaluates `load(order)` and compares it to `old`.
1098
  - If the two are not equivalent, returns.
@@ -1102,22 +1384,22 @@ void wait(shared_ptr<T> old, memory_order order = memory_order::seq_cst) const n
1102
  *Remarks:* Two `shared_ptr` objects are equivalent if they store the
1103
  same pointer and either share ownership or are both empty. This function
1104
  is an atomic waiting operation [[atomics.wait]].
1105
 
1106
  ``` cpp
1107
- void notify_one() noexcept;
1108
  ```
1109
 
1110
  *Effects:* Unblocks the execution of at least one atomic waiting
1111
  operation that is eligible to be unblocked [[atomics.wait]] by this
1112
  call, if any such atomic waiting operations exist.
1113
 
1114
  *Remarks:* This function is an atomic notifying
1115
  operation [[atomics.wait]].
1116
 
1117
  ``` cpp
1118
- void notify_all() noexcept;
1119
  ```
1120
 
1121
  *Effects:* Unblocks the execution of all atomic waiting operations that
1122
  are eligible to be unblocked [[atomics.wait]] by this call.
1123
 
@@ -1133,33 +1415,35 @@ namespace std {
1133
 
1134
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
1135
  bool is_lock_free() const noexcept;
1136
 
1137
  constexpr atomic() noexcept;
1138
- atomic(weak_ptr<T> desired) noexcept;
1139
  atomic(const atomic&) = delete;
1140
  void operator=(const atomic&) = delete;
1141
 
1142
- weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
1143
- operator weak_ptr<T>() const noexcept;
1144
- void store(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
1145
- void operator=(weak_ptr<T> desired) noexcept;
 
1146
 
1147
- weak_ptr<T> exchange(weak_ptr<T> desired,
1148
  memory_order order = memory_order::seq_cst) noexcept;
1149
- bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
1150
  memory_order success, memory_order failure) noexcept;
1151
- bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
1152
  memory_order success, memory_order failure) noexcept;
1153
- bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
1154
  memory_order order = memory_order::seq_cst) noexcept;
1155
- bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
1156
  memory_order order = memory_order::seq_cst) noexcept;
1157
 
1158
- void wait(weak_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
1159
- void notify_one() noexcept;
1160
- void notify_all() noexcept;
 
1161
 
1162
  private:
1163
  weak_ptr<T> p; // exposition only
1164
  };
1165
  }
@@ -1167,14 +1451,14 @@ namespace std {
1167
 
1168
  ``` cpp
1169
  constexpr atomic() noexcept;
1170
  ```
1171
 
1172
- *Effects:* Initializes `p{}`.
1173
 
1174
  ``` cpp
1175
- atomic(weak_ptr<T> desired) noexcept;
1176
  ```
1177
 
1178
  *Effects:* Initializes the object with the value `desired`.
1179
  Initialization is not an atomic operation [[intro.multithread]].
1180
 
@@ -1184,63 +1468,64 @@ the just-constructed object `A` to another thread via
1184
  `memory_order::relaxed` operations on a suitable atomic pointer
1185
  variable, and then immediately accessing `A` in the receiving thread.
1186
  This results in undefined behavior. — *end note*]
1187
 
1188
  ``` cpp
1189
- void store(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
1190
  ```
1191
 
1192
- *Preconditions:* `order` is neither `memory_order::consume`,
1193
- `memory_order::acquire`, nor `memory_order::acq_rel`.
1194
 
1195
  *Effects:* Atomically replaces the value pointed to by `this` with the
1196
  value of `desired` as if by `p.swap(desired)`. Memory is affected
1197
  according to the value of `order`.
1198
 
1199
  ``` cpp
1200
- void operator=(weak_ptr<T> desired) noexcept;
1201
  ```
1202
 
1203
  *Effects:* Equivalent to `store(desired)`.
1204
 
1205
  ``` cpp
1206
- weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
1207
  ```
1208
 
1209
- *Preconditions:* `order` is neither `memory_order::release` nor
1210
- `memory_order::acq_rel`.
1211
 
1212
  *Effects:* Memory is affected according to the value of `order`.
1213
 
1214
  *Returns:* Atomically returns `p`.
1215
 
1216
  ``` cpp
1217
- operator weak_ptr<T>() const noexcept;
1218
  ```
1219
 
1220
  *Effects:* Equivalent to: `return load();`
1221
 
1222
  ``` cpp
1223
- weak_ptr<T> exchange(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
 
1224
  ```
1225
 
1226
  *Effects:* Atomically replaces `p` with `desired` as if by
1227
  `p.swap(desired)`. Memory is affected according to the value of `order`.
1228
  This is an atomic read-modify-write operation [[intro.races]].
1229
 
1230
  *Returns:* Atomically returns the value of `p` immediately before the
1231
  effects.
1232
 
1233
  ``` cpp
1234
- bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
1235
  memory_order success, memory_order failure) noexcept;
1236
- bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
1237
  memory_order success, memory_order failure) noexcept;
1238
  ```
1239
 
1240
- *Preconditions:* `failure` is neither `memory_order::release` nor
1241
- `memory_order::acq_rel`.
1242
 
1243
  *Effects:* If `p` is equivalent to `expected`, assigns `desired` to `p`
1244
  and has synchronization semantics corresponding to the value of
1245
  `success`, otherwise assigns `p` to `expected` and has synchronization
1246
  semantics corresponding to the value of `failure`.
@@ -1261,11 +1546,11 @@ object in the attempted atomic update. The `use_count` update
1261
  corresponding to the write to `expected` is part of the atomic
1262
  operation. The write to `expected` itself is not required to be part of
1263
  the atomic operation.
1264
 
1265
  ``` cpp
1266
- bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
1267
  memory_order order = memory_order::seq_cst) noexcept;
1268
  ```
1269
 
1270
  *Effects:* Equivalent to:
1271
 
@@ -1277,11 +1562,11 @@ where `fail_order` is the same as `order` except that a value of
1277
  `memory_order::acq_rel` shall be replaced by the value
1278
  `memory_order::acquire` and a value of `memory_order::release` shall be
1279
  replaced by the value `memory_order::relaxed`.
1280
 
1281
  ``` cpp
1282
- bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
1283
  memory_order order = memory_order::seq_cst) noexcept;
1284
  ```
1285
 
1286
  *Effects:* Equivalent to:
1287
 
@@ -1293,15 +1578,15 @@ where `fail_order` is the same as `order` except that a value of
1293
  `memory_order::acq_rel` shall be replaced by the value
1294
  `memory_order::acquire` and a value of `memory_order::release` shall be
1295
  replaced by the value `memory_order::relaxed`.
1296
 
1297
  ``` cpp
1298
- void wait(weak_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
1299
  ```
1300
 
1301
- *Preconditions:* `order` is neither `memory_order::release` nor
1302
- `memory_order::acq_rel`.
1303
 
1304
  *Effects:* Repeatedly performs the following steps, in order:
1305
 
1306
  - Evaluates `load(order)` and compares it to `old`.
1307
  - If the two are not equivalent, returns.
@@ -1311,22 +1596,22 @@ void wait(weak_ptr<T> old, memory_order order = memory_order::seq_cst) const noe
1311
  *Remarks:* Two `weak_ptr` objects are equivalent if they store the same
1312
  pointer and either share ownership or are both empty. This function is
1313
  an atomic waiting operation [[atomics.wait]].
1314
 
1315
  ``` cpp
1316
- void notify_one() noexcept;
1317
  ```
1318
 
1319
  *Effects:* Unblocks the execution of at least one atomic waiting
1320
  operation that is eligible to be unblocked [[atomics.wait]] by this
1321
  call, if any such atomic waiting operations exist.
1322
 
1323
  *Remarks:* This function is an atomic notifying
1324
  operation [[atomics.wait]].
1325
 
1326
  ``` cpp
1327
- void notify_all() noexcept;
1328
  ```
1329
 
1330
  *Effects:* Unblocks the execution of all atomic waiting operations that
1331
  are eligible to be unblocked [[atomics.wait]] by this call.
1332
 
 
17
  atomic(const atomic&) = delete;
18
  atomic& operator=(const atomic&) = delete;
19
  atomic& operator=(const atomic&) volatile = delete;
20
 
21
  T load(memory_order = memory_order::seq_cst) const volatile noexcept;
22
+ constexpr T load(memory_order = memory_order::seq_cst) const noexcept;
23
  operator T() const volatile noexcept;
24
+ constexpr operator T() const noexcept;
25
  void store(T, memory_order = memory_order::seq_cst) volatile noexcept;
26
+ constexpr void store(T, memory_order = memory_order::seq_cst) noexcept;
27
  T operator=(T) volatile noexcept;
28
+ constexpr T operator=(T) noexcept;
29
 
30
  T exchange(T, memory_order = memory_order::seq_cst) volatile noexcept;
31
+ constexpr T exchange(T, memory_order = memory_order::seq_cst) noexcept;
32
  bool compare_exchange_weak(T&, T, memory_order, memory_order) volatile noexcept;
33
+ constexpr bool compare_exchange_weak(T&, T, memory_order, memory_order) noexcept;
34
  bool compare_exchange_strong(T&, T, memory_order, memory_order) volatile noexcept;
35
+ constexpr bool compare_exchange_strong(T&, T, memory_order, memory_order) noexcept;
36
  bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) volatile noexcept;
37
+ constexpr bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) noexcept;
38
  bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) volatile noexcept;
39
+ constexpr bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) noexcept;
40
 
41
  void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept;
42
+ constexpr void wait(T, memory_order = memory_order::seq_cst) const noexcept;
43
  void notify_one() volatile noexcept;
44
+ constexpr void notify_one() noexcept;
45
  void notify_all() volatile noexcept;
46
+ constexpr void notify_all() noexcept;
47
  };
48
  }
49
  ```
50
 
51
  The template argument for `T` shall meet the *Cpp17CopyConstructible*
 
53
  of
54
 
55
  - `is_trivially_copyable_v<T>`,
56
  - `is_copy_constructible_v<T>`,
57
  - `is_move_constructible_v<T>`,
58
+ - `is_copy_assignable_v<T>`,
59
+ - `is_move_assignable_v<T>`, or
60
+ - `is_same_v<T, remove_cv_t<T>>`,
61
 
62
  is `false`.
63
 
64
  [*Note 1*: Type arguments that are not also statically initializable
65
  can be difficult to use. — *end note*]
66
 
67
+ The specialization `atomic<bool>` is a standard-layout struct. It has a
68
+ trivial destructor.
69
 
70
  [*Note 2*: The representation of an atomic specialization need not have
71
  the same size and alignment requirement as its corresponding argument
72
  type. — *end note*]
73
 
 
75
 
76
  ``` cpp
77
  constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>);
78
  ```
79
 
80
+ *Constraints:* `is_default_constructible_v<T>` is `true`.
81
 
82
  *Effects:* Initializes the atomic object with the value of `T()`.
83
  Initialization is not an atomic operation [[intro.multithread]].
84
 
85
  ``` cpp
 
119
  consistent with the value of `is_always_lock_free` for the same
120
  type. — *end note*]
121
 
122
  ``` cpp
123
  void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
124
+ constexpr void store(T desired, memory_order order = memory_order::seq_cst) noexcept;
125
  ```
126
 
127
  *Constraints:* For the `volatile` overload of this function,
128
  `is_always_lock_free` is `true`.
129
 
130
+ *Preconditions:* `order` is `memory_order::relaxed`,
131
+ `memory_order::release`, or `memory_order::seq_cst`.
 
132
 
133
  *Effects:* Atomically replaces the value pointed to by `this` with the
134
  value of `desired`. Memory is affected according to the value of
135
  `order`.
136
 
137
  ``` cpp
138
  T operator=(T desired) volatile noexcept;
139
+ constexpr T operator=(T desired) noexcept;
140
  ```
141
 
142
  *Constraints:* For the `volatile` overload of this function,
143
  `is_always_lock_free` is `true`.
144
 
 
146
 
147
  *Returns:* `desired`.
148
 
149
  ``` cpp
150
  T load(memory_order order = memory_order::seq_cst) const volatile noexcept;
151
+ constexpr T load(memory_order order = memory_order::seq_cst) const noexcept;
152
  ```
153
 
154
  *Constraints:* For the `volatile` overload of this function,
155
  `is_always_lock_free` is `true`.
156
 
157
+ *Preconditions:* `order` is `memory_order::relaxed`,
158
+ `memory_order::acquire`, or `memory_order::seq_cst`.
159
 
160
  *Effects:* Memory is affected according to the value of `order`.
161
 
162
  *Returns:* Atomically returns the value pointed to by `this`.
163
 
164
  ``` cpp
165
  operator T() const volatile noexcept;
166
+ constexpr operator T() const noexcept;
167
  ```
168
 
169
  *Constraints:* For the `volatile` overload of this function,
170
  `is_always_lock_free` is `true`.
171
 
172
  *Effects:* Equivalent to: `return load();`
173
 
174
  ``` cpp
175
  T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
176
+ constexpr T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept;
177
  ```
178
 
179
  *Constraints:* For the `volatile` overload of this function,
180
  `is_always_lock_free` is `true`.
181
 
 
188
  before the effects.
189
 
190
  ``` cpp
191
  bool compare_exchange_weak(T& expected, T desired,
192
  memory_order success, memory_order failure) volatile noexcept;
193
+ constexpr bool compare_exchange_weak(T& expected, T desired,
194
  memory_order success, memory_order failure) noexcept;
195
  bool compare_exchange_strong(T& expected, T desired,
196
  memory_order success, memory_order failure) volatile noexcept;
197
+ constexpr bool compare_exchange_strong(T& expected, T desired,
198
  memory_order success, memory_order failure) noexcept;
199
  bool compare_exchange_weak(T& expected, T desired,
200
  memory_order order = memory_order::seq_cst) volatile noexcept;
201
+ constexpr bool compare_exchange_weak(T& expected, T desired,
202
  memory_order order = memory_order::seq_cst) noexcept;
203
  bool compare_exchange_strong(T& expected, T desired,
204
  memory_order order = memory_order::seq_cst) volatile noexcept;
205
+ constexpr bool compare_exchange_strong(T& expected, T desired,
206
  memory_order order = memory_order::seq_cst) noexcept;
207
  ```
208
 
209
  *Constraints:* For the `volatile` overload of this function,
210
  `is_always_lock_free` is `true`.
211
 
212
+ *Preconditions:* `failure` is `memory_order::relaxed`,
213
+ `memory_order::acquire`, or `memory_order::seq_cst`.
214
 
215
  *Effects:* Retrieves the value in `expected`. It then atomically
216
  compares the value representation of the value pointed to by `this` for
217
  equality with that previously retrieved from `expected`, and if true,
218
  replaces the value pointed to by `this` with that in `desired`. If and
 
297
 
298
  [*Note 6*: Under cases where the `memcpy` and `memcmp` semantics of the
299
  compare-and-exchange operations apply, the comparisons can fail for
300
  values that compare equal with `operator==` if the value representation
301
  has trap bits or alternate representations of the same value. Notably,
302
+ on implementations conforming to ISO/IEC 60559, floating-point `-0.0`
303
+ and `+0.0` will not compare equal with `memcmp` but will compare equal
304
+ with `operator==`, and NaNs with the same payload will compare equal
305
+ with `memcmp` but will not compare equal with
306
  `operator==`. — *end note*]
307
 
308
  [*Note 7*:
309
 
310
  Because compare-and-exchange acts on an object’s value representation,
 
351
 
352
  — *end note*]
353
 
354
  ``` cpp
355
  void wait(T old, memory_order order = memory_order::seq_cst) const volatile noexcept;
356
+ constexpr void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
357
  ```
358
 
359
+ *Preconditions:* `order` is `memory_order::relaxed`,
360
+ `memory_order::acquire`, or `memory_order::seq_cst`.
361
 
362
  *Effects:* Repeatedly performs the following steps, in order:
363
 
364
  - Evaluates `load(order)` and compares its value representation for
365
  equality against that of `old`.
 
370
  *Remarks:* This function is an atomic waiting
371
  operation [[atomics.wait]].
372
 
373
  ``` cpp
374
  void notify_one() volatile noexcept;
375
+ constexpr void notify_one() noexcept;
376
  ```
377
 
378
  *Effects:* Unblocks the execution of at least one atomic waiting
379
  operation that is eligible to be unblocked [[atomics.wait]] by this
380
  call, if any such atomic waiting operations exist.
 
382
  *Remarks:* This function is an atomic notifying
383
  operation [[atomics.wait]].
384
 
385
  ``` cpp
386
  void notify_all() volatile noexcept;
387
+ constexpr void notify_all() noexcept;
388
  ```
389
 
390
  *Effects:* Unblocks the execution of all atomic waiting operations that
391
  are eligible to be unblocked [[atomics.wait]] by this call.
392
 
 
422
  atomic(const atomic&) = delete;
423
  atomic& operator=(const atomic&) = delete;
424
  atomic& operator=(const atomic&) volatile = delete;
425
 
426
  void store(integral-type, memory_order = memory_order::seq_cst) volatile noexcept;
427
+ constexpr void store(integral-type, memory_order = memory_order::seq_cst) noexcept;
428
  integral-type operator=(integral-type) volatile noexcept;
429
+ constexpr integral-type operator=(integral-type) noexcept;
430
  integral-type load(memory_order = memory_order::seq_cst) const volatile noexcept;
431
+ constexpr integral-type load(memory_order = memory_order::seq_cst) const noexcept;
432
  operator integral-type() const volatile noexcept;
433
+ constexpr operator integral-type() const noexcept;
434
 
435
  integral-type exchange(integral-type,
436
  memory_order = memory_order::seq_cst) volatile noexcept;
437
+ constexpr integral-type exchange(integral-type,
438
  memory_order = memory_order::seq_cst) noexcept;
439
  bool compare_exchange_weak(integral-type&, integral-type,
440
  memory_order, memory_order) volatile noexcept;
441
+ constexpr bool compare_exchange_weak(integral-type&, integral-type,
442
  memory_order, memory_order) noexcept;
443
  bool compare_exchange_strong(integral-type&, integral-type,
444
  memory_order, memory_order) volatile noexcept;
445
+ constexpr bool compare_exchange_strong(integral-type&, integral-type,
446
  memory_order, memory_order) noexcept;
447
  bool compare_exchange_weak(integral-type&, integral-type,
448
  memory_order = memory_order::seq_cst) volatile noexcept;
449
+ constexpr bool compare_exchange_weak(integral-type&, integral-type,
450
  memory_order = memory_order::seq_cst) noexcept;
451
  bool compare_exchange_strong(integral-type&, integral-type,
452
  memory_order = memory_order::seq_cst) volatile noexcept;
453
+ constexpr bool compare_exchange_strong(integral-type&, integral-type,
454
  memory_order = memory_order::seq_cst) noexcept;
455
 
456
  integral-type fetch_add(integral-type,
457
  memory_order = memory_order::seq_cst) volatile noexcept;
458
+ constexpr integral-type fetch_add(integral-type,
459
  memory_order = memory_order::seq_cst) noexcept;
460
  integral-type fetch_sub(integral-type,
461
  memory_order = memory_order::seq_cst) volatile noexcept;
462
+ constexpr integral-type fetch_sub(integral-type,
463
  memory_order = memory_order::seq_cst) noexcept;
464
  integral-type fetch_and(integral-type,
465
  memory_order = memory_order::seq_cst) volatile noexcept;
466
+ constexpr integral-type fetch_and(integral-type,
467
  memory_order = memory_order::seq_cst) noexcept;
468
  integral-type fetch_or(integral-type,
469
  memory_order = memory_order::seq_cst) volatile noexcept;
470
+ constexpr integral-type fetch_or(integral-type,
471
  memory_order = memory_order::seq_cst) noexcept;
472
  integral-type fetch_xor(integral-type,
473
  memory_order = memory_order::seq_cst) volatile noexcept;
474
+ constexpr integral-type fetch_xor(integral-type,
475
+ memory_order = memory_order::seq_cst) noexcept;
476
+ integral-type fetch_max(integral-type,
477
+ memory_order = memory_order::seq_cst) volatile noexcept;
478
+ constexpr integral-type fetch_max(integral-type,
479
+ memory_order = memory_order::seq_cst) noexcept;
480
+ integral-type fetch_min(integral-type,
481
+ memory_order = memory_order::seq_cst) volatile noexcept;
482
+ constexpr integral-type fetch_min(integral-type,
483
+ memory_order = memory_order::seq_cst) noexcept;
484
+
485
+ void store_add(integral-type,
486
+ memory_order = memory_order::seq_cst) volatile noexcept;
487
+ constexpr void store_add(integral-type,
488
+ memory_order = memory_order::seq_cst) noexcept;
489
+ void store_sub(integral-type,
490
+ memory_order = memory_order::seq_cst) volatile noexcept;
491
+ constexpr void store_sub(integral-type,
492
+ memory_order = memory_order::seq_cst) noexcept;
493
+ void store_and(integral-type,
494
+ memory_order = memory_order::seq_cst) volatile noexcept;
495
+ constexpr void store_and(integral-type,
496
+ memory_order = memory_order::seq_cst) noexcept;
497
+ void store_or(integral-type,
498
+ memory_order = memory_order::seq_cst) volatile noexcept;
499
+ constexpr void store_or(integral-type,
500
+ memory_order = memory_order::seq_cst) noexcept;
501
+ void store_xor(integral-type,
502
+ memory_order = memory_order::seq_cst) volatile noexcept;
503
+ constexpr void store_xor(integral-type,
504
+ memory_order = memory_order::seq_cst) noexcept;
505
+ void store_max(integral-type,
506
+ memory_order = memory_order::seq_cst) volatile noexcept;
507
+ constexpr void store_max(integral-type,
508
+ memory_order = memory_order::seq_cst) noexcept;
509
+ void store_min(integral-type,
510
+ memory_order = memory_order::seq_cst) volatile noexcept;
511
+ constexpr void store_min(integral-type,
512
  memory_order = memory_order::seq_cst) noexcept;
513
 
514
  integral-type operator++(int) volatile noexcept;
515
+ constexpr integral-type operator++(int) noexcept;
516
  integral-type operator--(int) volatile noexcept;
517
+ constexpr integral-type operator--(int) noexcept;
518
  integral-type operator++() volatile noexcept;
519
+ constexpr integral-type operator++() noexcept;
520
  integral-type operator--() volatile noexcept;
521
+ constexpr integral-type operator--() noexcept;
522
  integral-type operator+=(integral-type) volatile noexcept;
523
+ constexpr integral-type operator+=(integral-type) noexcept;
524
  integral-type operator-=(integral-type) volatile noexcept;
525
+ constexpr integral-type operator-=(integral-type) noexcept;
526
  integral-type operator&=(integral-type) volatile noexcept;
527
+ constexpr integral-type operator&=(integral-type) noexcept;
528
  integral-type operator|=(integral-type) volatile noexcept;
529
+ constexpr integral-type operator|=(integral-type) noexcept;
530
  integral-type operator^=(integral-type) volatile noexcept;
531
+ constexpr integral-type operator^=(integral-type) noexcept;
532
 
533
  void wait(integral-type, memory_order = memory_order::seq_cst) const volatile noexcept;
534
+ constexpr void wait(integral-type, memory_order = memory_order::seq_cst) const noexcept;
535
  void notify_one() volatile noexcept;
536
+ constexpr void notify_one() noexcept;
537
  void notify_all() volatile noexcept;
538
+ constexpr void notify_all() noexcept;
539
  };
540
  }
541
  ```
542
 
543
  The atomic integral specializations are standard-layout structs. They
 
551
  [[atomic.types.int.comp]].
552
 
553
  **Table: Atomic arithmetic computations** <a id="atomic.types.int.comp">[atomic.types.int.comp]</a>
554
 
555
  | | | | | | |
556
+ | ----- | --- | ----------- | ----- | --- | -------------------- |
557
+ | `add` | `+` | addition | `and` | `&` | bitwise and |
558
+ | `sub` | `-` | subtraction | `or` | `|` | bitwise inclusive or |
559
+ | `max` | | maximum | `xor` | `^` | bitwise exclusive or |
560
+ | `min` | | minimum | | | |
561
 
562
  ``` cpp
563
+ integral-type fetch_key(integral-type operand,
564
+ memory_order order = memory_order::seq_cst) volatile noexcept;
565
+ constexpr integral-type fetch_key(integral-type operand,
566
+ memory_order order = memory_order::seq_cst) noexcept;
567
  ```
568
 
569
  *Constraints:* For the `volatile` overload of this function,
570
  `is_always_lock_free` is `true`.
571
 
 
576
  operations [[intro.multithread]].
577
 
578
  *Returns:* Atomically, the value pointed to by `this` immediately before
579
  the effects.
580
 
581
+ *Remarks:* Except for `fetch_max` and `fetch_min`, for signed integer
582
+ types the result is as if the object value and parameters were converted
583
+ to their corresponding unsigned types, the computation performed on
584
+ those types, and the result converted back to the signed type.
585
 
586
  [*Note 1*: There are no undefined results arising from the
587
  computation. — *end note*]
588
 
589
+ For `fetch_max` and `fetch_min`, the maximum and minimum computation is
590
+ performed as if by `max` and `min` algorithms [[alg.min.max]],
591
+ respectively, with the object value and the first parameter as the
592
+ arguments.
593
+
594
  ``` cpp
595
+ void store_key(integral-type operand,
596
+ memory_order order = memory_order::seq_cst) volatile noexcept;
597
+ constexpr void store_key(integral-type operand,
598
+ memory_order order = memory_order::seq_cst) noexcept;
599
+ ```
600
+
601
+ *Constraints:* For the `volatile` overload of this function,
602
+ `is_always_lock_free` is `true`.
603
+
604
+ *Preconditions:* `order` is `memory_order::relaxed`,
605
+ `memory_order::release`, or `memory_order::seq_cst`.
606
+
607
+ *Effects:* Atomically replaces the value pointed to by `this` with the
608
+ result of the computation applied to the value pointed to by `this` and
609
+ the given `operand`. Memory is affected according to the value of
610
+ `order`. These operations are atomic modify-write
611
+ operations [[atomics.order]].
612
+
613
+ *Remarks:* Except for `store_max` and `store_min`, for signed integer
614
+ types, the result is as if the value pointed to by `this` and parameters
615
+ were converted to their corresponding unsigned types, the computation
616
+ performed on those types, and the result converted back to the signed
617
+ type.
618
+
619
+ [*Note 2*: There are no undefined results arising from the
620
+ computation. — *end note*]
621
+
622
+ For `store_max` and `store_min`, the maximum and minimum computation is
623
+ performed as if by `max` and `min` algorithms [[alg.min.max]],
624
+ respectively, with the value pointed to by `this` and the first
625
+ parameter as the arguments.
626
+
627
+ ``` cpp
628
+ integral-type operator op=(integral-type operand) volatile noexcept;
629
+ constexpr integral-type operator op=(integral-type operand) noexcept;
630
  ```
631
 
632
  *Constraints:* For the `volatile` overload of this function,
633
  `is_always_lock_free` is `true`.
634
 
 
658
  atomic(const atomic&) = delete;
659
  atomic& operator=(const atomic&) = delete;
660
  atomic& operator=(const atomic&) volatile = delete;
661
 
662
  void store(floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept;
663
+ constexpr void store(floating-point-type, memory_order = memory_order::seq_cst) noexcept;
664
  floating-point-type operator=(floating-point-type) volatile noexcept;
665
+ constexpr floating-point-type operator=(floating-point-type) noexcept;
666
  floating-point-type load(memory_order = memory_order::seq_cst) volatile noexcept;
667
+ constexpr floating-point-type load(memory_order = memory_order::seq_cst) noexcept;
668
  operator floating-point-type() volatile noexcept;
669
+ constexpr operator floating-point-type() noexcept;
670
 
671
  floating-point-type exchange(floating-point-type,
672
  memory_order = memory_order::seq_cst) volatile noexcept;
673
+ constexpr floating-point-type exchange(floating-point-type,
674
  memory_order = memory_order::seq_cst) noexcept;
675
  bool compare_exchange_weak(floating-point-type&, floating-point-type,
676
  memory_order, memory_order) volatile noexcept;
677
+ constexpr bool compare_exchange_weak(floating-point-type&, floating-point-type,
678
  memory_order, memory_order) noexcept;
679
  bool compare_exchange_strong(floating-point-type&, floating-point-type,
680
  memory_order, memory_order) volatile noexcept;
681
+ constexpr bool compare_exchange_strong(floating-point-type&, floating-point-type,
682
  memory_order, memory_order) noexcept;
683
  bool compare_exchange_weak(floating-point-type&, floating-point-type,
684
  memory_order = memory_order::seq_cst) volatile noexcept;
685
+ constexpr bool compare_exchange_weak(floating-point-type&, floating-point-type,
686
  memory_order = memory_order::seq_cst) noexcept;
687
  bool compare_exchange_strong(floating-point-type&, floating-point-type,
688
  memory_order = memory_order::seq_cst) volatile noexcept;
689
+ constexpr bool compare_exchange_strong(floating-point-type&, floating-point-type,
690
  memory_order = memory_order::seq_cst) noexcept;
691
 
692
  floating-point-type fetch_add(floating-point-type,
693
  memory_order = memory_order::seq_cst) volatile noexcept;
694
+ constexpr floating-point-type fetch_add(floating-point-type,
695
  memory_order = memory_order::seq_cst) noexcept;
696
  floating-point-type fetch_sub(floating-point-type,
697
  memory_order = memory_order::seq_cst) volatile noexcept;
698
+ constexpr floating-point-type fetch_sub(floating-point-type,
699
+ memory_order = memory_order::seq_cst) noexcept;
700
+ floating-point-type fetch_max(floating-point-type,
701
+ memory_order = memory_order::seq_cst) volatile noexcept;
702
+ constexpr floating-point-type fetch_max(floating-point-type,
703
+ memory_order = memory_order::seq_cst) noexcept;
704
+ floating-point-type fetch_min(floating-point-type,
705
+ memory_order = memory_order::seq_cst) volatile noexcept;
706
+ constexpr floating-poin-typet fetch_min(floating-point-type,
707
+ memory_order = memory_order::seq_cst) noexcept;
708
+ floating-point-type fetch_fmaximum(floating-point-type,
709
+ memory_order = memory_order::seq_cst) volatile noexcept;
710
+ constexpr floating-point-type fetch_fmaximum(floating-point-type,
711
+ memory_order = memory_order::seq_cst) noexcept;
712
+ floating-point-type fetch_fminimum(floating-point-type,
713
+ memory_order = memory_order::seq_cst) volatile noexcept;
714
+ constexpr floating-point-type fetch_fminimum(floating-point-type,
715
+ memory_order = memory_order::seq_cst) noexcept;
716
+ floating-point-type fetch_fmaximum_num(
717
+ floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept;
718
+ constexpr floating-point-type fetch_fmaximum_num(
719
+ floating-point-type, memory_order = memory_order::seq_cst) noexcept;
720
+ floating-point-type fetch_fminimum_num(
721
+ floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept;
722
+ constexpr floating-point-type fetch_fminimum_num(
723
+ floating-point-type, memory_order = memory_order::seq_cst) noexcept;
724
+
725
+ void store_add(floating-point-type,
726
+ memory_order = memory_order::seq_cst) volatile noexcept;
727
+ constexpr void store_add(floating-point-type,
728
+ memory_order = memory_order::seq_cst) noexcept;
729
+ void store_sub(floating-point-type,
730
+ memory_order = memory_order::seq_cst) volatile noexcept;
731
+ constexpr void store_sub(floating-point-type,
732
+ memory_order = memory_order::seq_cst) noexcept;
733
+ void store_max(floating-point-type,
734
+ memory_order = memory_order::seq_cst) volatile noexcept;
735
+ constexpr void store_max(floating-point-type,
736
+ memory_order = memory_order::seq_cst) noexcept;
737
+ void store_min(floating-point-type,
738
+ memory_order = memory_order::seq_cst) volatile noexcept;
739
+ constexpr void store_min(floating-point-type,
740
+ memory_order = memory_order::seq_cst) noexcept;
741
+ void store_fmaximum(floating-point-type,
742
+ memory_order = memory_order::seq_cst) volatile noexcept;
743
+ constexpr void store_fmaximum(floating-point-type,
744
+ memory_order = memory_order::seq_cst) noexcept;
745
+ void store_fminimum(floating-point-type,
746
+ memory_order = memory_order::seq_cst) volatile noexcept;
747
+ constexpr void store_fminimum(floating-point-type,
748
+ memory_order = memory_order::seq_cst) noexcept;
749
+ void store_fmaximum_num(floating-point-type,
750
+ memory_order = memory_order::seq_cst) volatile noexcept;
751
+ constexpr void store_fmaximum_num(floating-point-type,
752
+ memory_order = memory_order::seq_cst) noexcept;
753
+ void store_fminimum_num(floating-point-type,
754
+ memory_order = memory_order::seq_cst) volatile noexcept;
755
+ constexpr void store_fminimum_num(floating-point-type,
756
  memory_order = memory_order::seq_cst) noexcept;
757
 
758
  floating-point-type operator+=(floating-point-type) volatile noexcept;
759
+ constexpr floating-point-type operator+=(floating-point-type) noexcept;
760
  floating-point-type operator-=(floating-point-type) volatile noexcept;
761
+ constexpr floating-point-type operator-=(floating-point-type) noexcept;
762
 
763
  void wait(floating-point-type, memory_order = memory_order::seq_cst) const volatile noexcept;
764
+ constexpr void wait(floating-point-type,
765
+ memory_order = memory_order::seq_cst) const noexcept;
766
  void notify_one() volatile noexcept;
767
+ constexpr void notify_one() noexcept;
768
  void notify_all() volatile noexcept;
769
+ constexpr void notify_all() noexcept;
770
  };
771
  }
772
  ```
773
 
774
  The atomic floating-point specializations are standard-layout structs.
 
777
  Descriptions are provided below only for members that differ from the
778
  primary template.
779
 
780
  The following operations perform arithmetic addition and subtraction
781
  computations. The correspondence among key, operator, and computation is
782
+ specified in [[atomic.types.int.comp]], except for the keys `max`,
783
+ `min`, `fmaximum`, `fminimum`, `fmaximum_num`, and `fminimum_num`, which
784
+ are specified below.
785
 
786
  ``` cpp
787
+ floating-point-type fetch_key(floating-point-type operand,
788
+ memory_order order = memory_order::seq_cst) volatile noexcept;
789
+ constexpr floating-point-type fetch_key(floating-point-type operand,
790
+ memory_order order = memory_order::seq_cst) noexcept;
791
  ```
792
 
793
  *Constraints:* For the `volatile` overload of this function,
794
  `is_always_lock_free` is `true`.
795
 
 
810
  the floating-point type [[limits.syn]]. The floating-point
811
  environment [[cfenv]] for atomic arithmetic operations on
812
  *`floating-point-type`* may be different than the calling thread’s
813
  floating-point environment.
814
 
815
+ - For `fetch_fmaximum` and `fetch_fminimum`, the maximum and minimum
816
+ computation is performed as if by `fmaximum` and `fminimum`,
817
+ respectively, with the value pointed to by `this` and the first
818
+ parameter as the arguments.
819
+ - For `fetch_fmaximum_num` and `fetch_fminimum_num`, the maximum and
820
+ minimum computation is performed as if by `fmaximum_num` and
821
+ `fminimum_num`, respectively, with the value pointed to by `this` and
822
+ the first parameter as the arguments.
823
+ - For `fetch_max` and `fetch_min`, the maximum and minimum computation
824
+ is performed as if by `fmaximum_num` and `fminimum_num`, respectively,
825
+ with the value pointed to by `this` and the first parameter as the
826
+ arguments, except that:
827
+ - If both arguments are NaN, an unspecified NaN value replaces the
828
+ value pointed to by `this`.
829
+ - If exactly one argument is a NaN, either the other argument or an
830
+ unspecified NaN value replaces the value pointed to by `this`; it is
831
+ unspecified which.
832
+ - If the arguments are differently signed zeros, which of these values
833
+ replaces the value pointed to by this is unspecified.
834
+
835
+ *Recommended practice:* The implementation of `fetch_max` and
836
+ `fetch_min` should treat negative zero as smaller than positive zero.
837
+
838
  ``` cpp
839
+ void store_key(floating-point-type operand,
840
+ memory_order order = memory_order::seq_cst) volatile noexcept;
841
+ constexpr void store_key(floating-point-type operand,
842
+ memory_order order = memory_order::seq_cst) noexcept;
843
+ ```
844
+
845
+ *Constraints:* For the `volatile` overload of this function,
846
+ `is_always_lock_free` is `true`.
847
+
848
+ *Preconditions:* `order` is `memory_order::relaxed`,
849
+ `memory_order::release`, or `memory_order::seq_cst`.
850
+
851
+ *Effects:* Atomically replaces the value pointed to by `this` with the
852
+ result of the computation applied to the value pointed to by `this` and
853
+ the given operand. Memory is affected according to the value of `order`.
854
+ These operations are atomic modify-write operations [[atomics.order]].
855
+
856
+ *Remarks:* If the result is not a representable value for its
857
+ type [[expr.pre]] the result is unspecified, but the operations
858
+ otherwise have no undefined behavior. Atomic arithmetic operations on
859
+ *`floating-point-type`* should conform to the
860
+ `numeric_limits<`*`floating-point-type`*`>` traits associated with the
861
+ floating-point type [[limits.syn]]. The floating-point
862
+ environment [[cfenv]] for atomic arithmetic operations on
863
+ *`floating-point-type`* may be different than the calling thread’s
864
+ floating-point environment. The arithmetic rules of floating-point
865
+ atomic modify-write operations may be different from operations on
866
+ floating-point types or atomic floating-point types.
867
+
868
+ [*Note 1*: Tree reductions are permitted for atomic modify-write
869
+ operations. — *end note*]
870
+
871
+ - For `store_fmaximum` and `store_fminimum`, the maximum and minimum
872
+ computation is performed as if by `fmaximum` and `fminimum`,
873
+ respectively, with the value pointed to by `this` and the first
874
+ parameter as the arguments.
875
+ - For `store_fmaximum_num` and `store_fminimum_num`, the maximum and
876
+ minimum computation is performed as if by `fmaximum_num` and
877
+ `fminimum_num`, respectively, with the value pointed to by `this` and
878
+ the first parameter as the arguments.
879
+ - For `store_max` and `store_min`, the maximum and minimum computation
880
+ is performed as if by `fmaximum_num` and `fminimum_num`, respectively,
881
+ with the value pointed to by `this` and the first parameter as the
882
+ arguments, except that:
883
+ - If both arguments are NaN, an unspecified NaN value replaces the
884
+ value pointed to by `this`.
885
+ - If exactly one argument is a NaN, either the other argument or an
886
+ unspecified NaN value replaces the value pointed to by `this`; it is
887
+ unspecified which.
888
+ - If the arguments are differently signed zeros, which of these values
889
+ replaces the value pointed to by `this` is unspecified.
890
+
891
+ *Recommended practice:* The implementation of `store_max` and
892
+ `store_min` should treat negative zero as smaller than positive zero.
893
+
894
+ ``` cpp
895
+ floating-point-type operator op=(floating-point-type operand) volatile noexcept;
896
+ constexpr floating-point-type operator op=(floating-point-type operand) noexcept;
897
  ```
898
 
899
  *Constraints:* For the `volatile` overload of this function,
900
  `is_always_lock_free` is `true`.
901
 
 
929
  atomic(const atomic&) = delete;
930
  atomic& operator=(const atomic&) = delete;
931
  atomic& operator=(const atomic&) volatile = delete;
932
 
933
  void store(T*, memory_order = memory_order::seq_cst) volatile noexcept;
934
+ constexpr void store(T*, memory_order = memory_order::seq_cst) noexcept;
935
  T* operator=(T*) volatile noexcept;
936
+ constexpr T* operator=(T*) noexcept;
937
  T* load(memory_order = memory_order::seq_cst) const volatile noexcept;
938
+ constexpr T* load(memory_order = memory_order::seq_cst) const noexcept;
939
  operator T*() const volatile noexcept;
940
+ constexpr operator T*() const noexcept;
941
 
942
  T* exchange(T*, memory_order = memory_order::seq_cst) volatile noexcept;
943
+ constexpr T* exchange(T*, memory_order = memory_order::seq_cst) noexcept;
944
  bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile noexcept;
945
+ constexpr bool compare_exchange_weak(T*&, T*, memory_order, memory_order) noexcept;
946
  bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile noexcept;
947
+ constexpr bool compare_exchange_strong(T*&, T*, memory_order, memory_order) noexcept;
948
  bool compare_exchange_weak(T*&, T*,
949
  memory_order = memory_order::seq_cst) volatile noexcept;
950
+ constexpr bool compare_exchange_weak(T*&, T*,
951
  memory_order = memory_order::seq_cst) noexcept;
952
  bool compare_exchange_strong(T*&, T*,
953
  memory_order = memory_order::seq_cst) volatile noexcept;
954
+ constexpr bool compare_exchange_strong(T*&, T*,
955
  memory_order = memory_order::seq_cst) noexcept;
956
 
957
  T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
958
+ constexpr T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
959
  T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
960
+ constexpr T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
961
+ T* fetch_max(T*, memory_order = memory_order::seq_cst) volatile noexcept;
962
+ constexpr T* fetch_max(T*, memory_order = memory_order::seq_cst) noexcept;
963
+ T* fetch_min(T*, memory_order = memory_order::seq_cst) volatile noexcept;
964
+ constexpr T* fetch_min(T*, memory_order = memory_order::seq_cst) noexcept;
965
+
966
+ void store_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
967
+ constexpr void store_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
968
+ void store_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
969
+ constexpr void store_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
970
+ void store_max(T*, memory_order = memory_order::seq_cst) volatile noexcept;
971
+ constexpr void store_max(T*, memory_order = memory_order::seq_cst) noexcept;
972
+ void store_min(T*, memory_order = memory_order::seq_cst) volatile noexcept;
973
+ constexpr void store_min(T*, memory_order = memory_order::seq_cst) noexcept;
974
 
975
  T* operator++(int) volatile noexcept;
976
+ constexpr T* operator++(int) noexcept;
977
  T* operator--(int) volatile noexcept;
978
+ constexpr T* operator--(int) noexcept;
979
  T* operator++() volatile noexcept;
980
+ constexpr T* operator++() noexcept;
981
  T* operator--() volatile noexcept;
982
+ constexpr T* operator--() noexcept;
983
  T* operator+=(ptrdiff_t) volatile noexcept;
984
+ constexpr T* operator+=(ptrdiff_t) noexcept;
985
  T* operator-=(ptrdiff_t) volatile noexcept;
986
+ constexpr T* operator-=(ptrdiff_t) noexcept;
987
 
988
  void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept;
989
+ constexpr void wait(T*, memory_order = memory_order::seq_cst) const noexcept;
990
  void notify_one() volatile noexcept;
991
+ constexpr void notify_one() noexcept;
992
  void notify_all() volatile noexcept;
993
+ constexpr void notify_all() noexcept;
994
  };
995
  }
996
  ```
997
 
998
  There is a partial specialization of the `atomic` class template for
 
1009
  **Table: Atomic pointer computations** <a id="atomic.types.pointer.comp">[atomic.types.pointer.comp]</a>
1010
 
1011
  | | | | | | |
1012
  | ----- | --- | -------- | ----- | --- | ----------- |
1013
  | `add` | `+` | addition | `sub` | `-` | subtraction |
1014
+ | `max` | | maximum | `min` | | minimum |
1015
 
1016
  ``` cpp
1017
+ T* fetch_key(\seeabovenc operand, memory_order order = memory_order::seq_cst) volatile noexcept;
1018
+ constexpr T* fetch_key(\seeabovenc operand, memory_order order = memory_order::seq_cst) noexcept;
1019
  ```
1020
 
1021
  *Constraints:* For the `volatile` overload of this function,
1022
  `is_always_lock_free` is `true`.
1023
 
 
1036
  the effects.
1037
 
1038
  *Remarks:* The result may be an undefined address, but the operations
1039
  otherwise have no undefined behavior.
1040
 
1041
+ For `fetch_max` and `fetch_min`, the maximum and minimum computation is
1042
+ performed as if by `max` and `min` algorithms [[alg.min.max]],
1043
+ respectively, with the object value and the first parameter as the
1044
+ arguments.
1045
+
1046
+ [*Note 2*: If the pointers point to different complete objects (or
1047
+ subobjects thereof), the `<` operator does not establish a strict weak
1048
+ ordering ([[cpp17.lessthancomparable]], [[expr.rel]]). — *end note*]
1049
+
1050
+ ``` cpp
1051
+ void store_key(\seeabovenc operand, memory_order order = memory_order::seq_cst) volatile noexcept;
1052
+ constexpr void store_key(\seeabovenc operand, memory_order order = memory_order::seq_cst) noexcept;
1053
+ ```
1054
+
1055
+ *Constraints:* For the `volatile` overload of this function,
1056
+ `is_always_lock_free` is `true`.
1057
+
1058
+ *Mandates:* `T` is a complete object type.
1059
+
1060
+ [*Note 3*: Pointer arithmetic on `void*` or function pointers is
1061
+ ill-formed. — *end note*]
1062
+
1063
+ *Effects:* Atomically replaces the value pointed to by `this` with the
1064
+ result of the computation applied to the value pointed to by `this` and
1065
+ the given `operand`. Memory is affected according to the value of
1066
+ `order`. These operations are atomic modify-write
1067
+ operations [[atomics.order]].
1068
+
1069
+ *Remarks:* The result may be an undefined address, but the operations
1070
+ otherwise have no undefined behavior. For `store_max` and `store_min`,
1071
+ the maximum and minimum computation is performed as if by `max` and
1072
+ `min` algorithms [[alg.min.max]], respectively, with the value pointed
1073
+ to by `this` and the first parameter as the arguments.
1074
+
1075
+ [*Note 4*: If the pointers point to different complete objects (or
1076
+ subobjects thereof), the `<` operator does not establish a strict weak
1077
+ ordering ([[cpp17.lessthancomparable]], [[expr.rel]]). — *end note*]
1078
+
1079
  ``` cpp
1080
  T* operator op=(ptrdiff_t operand) volatile noexcept;
1081
+ constexpr T* operator op=(ptrdiff_t operand) noexcept;
1082
  ```
1083
 
1084
  *Constraints:* For the `volatile` overload of this function,
1085
  `is_always_lock_free` is `true`.
1086
 
 
1089
 
1090
  #### Member operators common to integers and pointers to objects <a id="atomics.types.memop">[[atomics.types.memop]]</a>
1091
 
1092
  ``` cpp
1093
  value_type operator++(int) volatile noexcept;
1094
+ constexpr value_type operator++(int) noexcept;
1095
  ```
1096
 
1097
  *Constraints:* For the `volatile` overload of this function,
1098
  `is_always_lock_free` is `true`.
1099
 
1100
  *Effects:* Equivalent to: `return fetch_add(1);`
1101
 
1102
  ``` cpp
1103
  value_type operator--(int) volatile noexcept;
1104
+ constexpr value_type operator--(int) noexcept;
1105
  ```
1106
 
1107
  *Constraints:* For the `volatile` overload of this function,
1108
  `is_always_lock_free` is `true`.
1109
 
1110
  *Effects:* Equivalent to: `return fetch_sub(1);`
1111
 
1112
  ``` cpp
1113
  value_type operator++() volatile noexcept;
1114
+ constexpr value_type operator++() noexcept;
1115
  ```
1116
 
1117
  *Constraints:* For the `volatile` overload of this function,
1118
  `is_always_lock_free` is `true`.
1119
 
1120
  *Effects:* Equivalent to: `return fetch_add(1) + 1;`
1121
 
1122
  ``` cpp
1123
  value_type operator--() volatile noexcept;
1124
+ constexpr value_type operator--() noexcept;
1125
  ```
1126
 
1127
  *Constraints:* For the `volatile` overload of this function,
1128
  `is_always_lock_free` is `true`.
1129
 
 
1196
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
1197
  bool is_lock_free() const noexcept;
1198
 
1199
  constexpr atomic() noexcept;
1200
  constexpr atomic(nullptr_t) noexcept : atomic() { }
1201
+ constexpr atomic(shared_ptr<T> desired) noexcept;
1202
  atomic(const atomic&) = delete;
1203
  void operator=(const atomic&) = delete;
1204
 
1205
+ constexpr shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
1206
+ constexpr operator shared_ptr<T>() const noexcept;
1207
+ constexpr void store(shared_ptr<T> desired,
1208
+ memory_order order = memory_order::seq_cst) noexcept;
1209
+ constexpr void operator=(shared_ptr<T> desired) noexcept;
1210
+ constexpr void operator=(nullptr_t) noexcept;
1211
 
1212
+ constexpr shared_ptr<T> exchange(shared_ptr<T> desired,
1213
  memory_order order = memory_order::seq_cst) noexcept;
1214
+ constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
1215
  memory_order success, memory_order failure) noexcept;
1216
+ constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
1217
  memory_order success, memory_order failure) noexcept;
1218
+ constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
1219
  memory_order order = memory_order::seq_cst) noexcept;
1220
+ constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
1221
  memory_order order = memory_order::seq_cst) noexcept;
1222
 
1223
+ constexpr void wait(shared_ptr<T> old,
1224
+ memory_order order = memory_order::seq_cst) const noexcept;
1225
+ constexpr void notify_one() noexcept;
1226
+ constexpr void notify_all() noexcept;
1227
 
1228
  private:
1229
  shared_ptr<T> p; // exposition only
1230
  };
1231
  }
 
1233
 
1234
  ``` cpp
1235
  constexpr atomic() noexcept;
1236
  ```
1237
 
1238
+ *Effects:* Value-initializes `p`.
1239
 
1240
  ``` cpp
1241
+ constexpr atomic(shared_ptr<T> desired) noexcept;
1242
  ```
1243
 
1244
  *Effects:* Initializes the object with the value `desired`.
1245
  Initialization is not an atomic operation [[intro.multithread]].
1246
 
 
1250
  `memory_order::relaxed` operations on a suitable atomic pointer
1251
  variable, and then immediately accessing `A` in the receiving thread.
1252
  This results in undefined behavior. — *end note*]
1253
 
1254
  ``` cpp
1255
+ constexpr void store(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
1256
  ```
1257
 
1258
+ *Preconditions:* `order` is `memory_order::relaxed`,
1259
+ `memory_order::release`, or `memory_order::seq_cst`.
1260
 
1261
  *Effects:* Atomically replaces the value pointed to by `this` with the
1262
  value of `desired` as if by `p.swap(desired)`. Memory is affected
1263
  according to the value of `order`.
1264
 
1265
  ``` cpp
1266
+ constexpr void operator=(shared_ptr<T> desired) noexcept;
1267
  ```
1268
 
1269
  *Effects:* Equivalent to `store(desired)`.
1270
 
1271
  ``` cpp
1272
+ constexpr void operator=(nullptr_t) noexcept;
1273
  ```
1274
 
1275
+ *Effects:* Equivalent to `store(nullptr)`.
1276
+
1277
+ ``` cpp
1278
+ constexpr shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
1279
+ ```
1280
+
1281
+ *Preconditions:* `order` is `memory_order::relaxed`,
1282
+ `memory_order::acquire`, or `memory_order::seq_cst`.
1283
 
1284
  *Effects:* Memory is affected according to the value of `order`.
1285
 
1286
  *Returns:* Atomically returns `p`.
1287
 
1288
  ``` cpp
1289
+ constexpr operator shared_ptr<T>() const noexcept;
1290
  ```
1291
 
1292
  *Effects:* Equivalent to: `return load();`
1293
 
1294
  ``` cpp
1295
+ constexpr shared_ptr<T> exchange(shared_ptr<T> desired,
1296
+ memory_order order = memory_order::seq_cst) noexcept;
1297
  ```
1298
 
1299
  *Effects:* Atomically replaces `p` with `desired` as if by
1300
  `p.swap(desired)`. Memory is affected according to the value of `order`.
1301
  This is an atomic read-modify-write operation [[intro.races]].
1302
 
1303
  *Returns:* Atomically returns the value of `p` immediately before the
1304
  effects.
1305
 
1306
  ``` cpp
1307
+ constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
1308
  memory_order success, memory_order failure) noexcept;
1309
+ constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
1310
  memory_order success, memory_order failure) noexcept;
1311
  ```
1312
 
1313
+ *Preconditions:* `failure` is `memory_order::relaxed`,
1314
+ `memory_order::acquire`, or `memory_order::seq_cst`.
1315
 
1316
  *Effects:* If `p` is equivalent to `expected`, assigns `desired` to `p`
1317
  and has synchronization semantics corresponding to the value of
1318
  `success`, otherwise assigns `p` to `expected` and has synchronization
1319
  semantics corresponding to the value of `failure`.
 
1334
  corresponding to the write to `expected` is part of the atomic
1335
  operation. The write to `expected` itself is not required to be part of
1336
  the atomic operation.
1337
 
1338
  ``` cpp
1339
+ constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
1340
  memory_order order = memory_order::seq_cst) noexcept;
1341
  ```
1342
 
1343
  *Effects:* Equivalent to:
1344
 
 
1350
  `memory_order::acq_rel` shall be replaced by the value
1351
  `memory_order::acquire` and a value of `memory_order::release` shall be
1352
  replaced by the value `memory_order::relaxed`.
1353
 
1354
  ``` cpp
1355
+ constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
1356
  memory_order order = memory_order::seq_cst) noexcept;
1357
  ```
1358
 
1359
  *Effects:* Equivalent to:
1360
 
 
1366
  `memory_order::acq_rel` shall be replaced by the value
1367
  `memory_order::acquire` and a value of `memory_order::release` shall be
1368
  replaced by the value `memory_order::relaxed`.
1369
 
1370
  ``` cpp
1371
+ constexpr void wait(shared_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
1372
  ```
1373
 
1374
+ *Preconditions:* `order` is `memory_order::relaxed`,
1375
+ `memory_order::acquire`, or `memory_order::seq_cst`.
1376
 
1377
  *Effects:* Repeatedly performs the following steps, in order:
1378
 
1379
  - Evaluates `load(order)` and compares it to `old`.
1380
  - If the two are not equivalent, returns.
 
1384
  *Remarks:* Two `shared_ptr` objects are equivalent if they store the
1385
  same pointer and either share ownership or are both empty. This function
1386
  is an atomic waiting operation [[atomics.wait]].
1387
 
1388
  ``` cpp
1389
+ constexpr void notify_one() noexcept;
1390
  ```
1391
 
1392
  *Effects:* Unblocks the execution of at least one atomic waiting
1393
  operation that is eligible to be unblocked [[atomics.wait]] by this
1394
  call, if any such atomic waiting operations exist.
1395
 
1396
  *Remarks:* This function is an atomic notifying
1397
  operation [[atomics.wait]].
1398
 
1399
  ``` cpp
1400
+ constexpr void notify_all() noexcept;
1401
  ```
1402
 
1403
  *Effects:* Unblocks the execution of all atomic waiting operations that
1404
  are eligible to be unblocked [[atomics.wait]] by this call.
1405
 
 
1415
 
1416
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
1417
  bool is_lock_free() const noexcept;
1418
 
1419
  constexpr atomic() noexcept;
1420
+ constexpr atomic(weak_ptr<T> desired) noexcept;
1421
  atomic(const atomic&) = delete;
1422
  void operator=(const atomic&) = delete;
1423
 
1424
+ constexpr weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
1425
+ constexpr operator weak_ptr<T>() const noexcept;
1426
+ constexpr void store(weak_ptr<T> desired,
1427
+ memory_order order = memory_order::seq_cst) noexcept;
1428
+ constexpr void operator=(weak_ptr<T> desired) noexcept;
1429
 
1430
+ constexpr weak_ptr<T> exchange(weak_ptr<T> desired,
1431
  memory_order order = memory_order::seq_cst) noexcept;
1432
+ constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
1433
  memory_order success, memory_order failure) noexcept;
1434
+ constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
1435
  memory_order success, memory_order failure) noexcept;
1436
+ constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
1437
  memory_order order = memory_order::seq_cst) noexcept;
1438
+ constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
1439
  memory_order order = memory_order::seq_cst) noexcept;
1440
 
1441
+ constexpr void wait(weak_ptr<T> old,
1442
+ memory_order order = memory_order::seq_cst) const noexcept;
1443
+ constexpr void notify_one() noexcept;
1444
+ constexpr void notify_all() noexcept;
1445
 
1446
  private:
1447
  weak_ptr<T> p; // exposition only
1448
  };
1449
  }
 
1451
 
1452
  ``` cpp
1453
  constexpr atomic() noexcept;
1454
  ```
1455
 
1456
+ *Effects:* Value-initializes `p`.
1457
 
1458
  ``` cpp
1459
+ constexpr atomic(weak_ptr<T> desired) noexcept;
1460
  ```
1461
 
1462
  *Effects:* Initializes the object with the value `desired`.
1463
  Initialization is not an atomic operation [[intro.multithread]].
1464
 
 
1468
  `memory_order::relaxed` operations on a suitable atomic pointer
1469
  variable, and then immediately accessing `A` in the receiving thread.
1470
  This results in undefined behavior. — *end note*]
1471
 
1472
  ``` cpp
1473
+ constexpr void store(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
1474
  ```
1475
 
1476
+ *Preconditions:* `order` is `memory_order::relaxed`,
1477
+ `memory_order::release`, or `memory_order::seq_cst`.
1478
 
1479
  *Effects:* Atomically replaces the value pointed to by `this` with the
1480
  value of `desired` as if by `p.swap(desired)`. Memory is affected
1481
  according to the value of `order`.
1482
 
1483
  ``` cpp
1484
+ constexpr void operator=(weak_ptr<T> desired) noexcept;
1485
  ```
1486
 
1487
  *Effects:* Equivalent to `store(desired)`.
1488
 
1489
  ``` cpp
1490
+ constexpr weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
1491
  ```
1492
 
1493
+ *Preconditions:* `order` is `memory_order::relaxed`,
1494
+ `memory_order::acquire`, or `memory_order::seq_cst`.
1495
 
1496
  *Effects:* Memory is affected according to the value of `order`.
1497
 
1498
  *Returns:* Atomically returns `p`.
1499
 
1500
  ``` cpp
1501
+ constexpr operator weak_ptr<T>() const noexcept;
1502
  ```
1503
 
1504
  *Effects:* Equivalent to: `return load();`
1505
 
1506
  ``` cpp
1507
+ constexpr weak_ptr<T> exchange(weak_ptr<T> desired,
1508
+ memory_order order = memory_order::seq_cst) noexcept;
1509
  ```
1510
 
1511
  *Effects:* Atomically replaces `p` with `desired` as if by
1512
  `p.swap(desired)`. Memory is affected according to the value of `order`.
1513
  This is an atomic read-modify-write operation [[intro.races]].
1514
 
1515
  *Returns:* Atomically returns the value of `p` immediately before the
1516
  effects.
1517
 
1518
  ``` cpp
1519
+ constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
1520
  memory_order success, memory_order failure) noexcept;
1521
+ constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
1522
  memory_order success, memory_order failure) noexcept;
1523
  ```
1524
 
1525
+ *Preconditions:* `failure` is `memory_order::relaxed`,
1526
+ `memory_order::acquire`, or `memory_order::seq_cst`.
1527
 
1528
  *Effects:* If `p` is equivalent to `expected`, assigns `desired` to `p`
1529
  and has synchronization semantics corresponding to the value of
1530
  `success`, otherwise assigns `p` to `expected` and has synchronization
1531
  semantics corresponding to the value of `failure`.
 
1546
  corresponding to the write to `expected` is part of the atomic
1547
  operation. The write to `expected` itself is not required to be part of
1548
  the atomic operation.
1549
 
1550
  ``` cpp
1551
+ constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
1552
  memory_order order = memory_order::seq_cst) noexcept;
1553
  ```
1554
 
1555
  *Effects:* Equivalent to:
1556
 
 
1562
  `memory_order::acq_rel` shall be replaced by the value
1563
  `memory_order::acquire` and a value of `memory_order::release` shall be
1564
  replaced by the value `memory_order::relaxed`.
1565
 
1566
  ``` cpp
1567
+ constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
1568
  memory_order order = memory_order::seq_cst) noexcept;
1569
  ```
1570
 
1571
  *Effects:* Equivalent to:
1572
 
 
1578
  `memory_order::acq_rel` shall be replaced by the value
1579
  `memory_order::acquire` and a value of `memory_order::release` shall be
1580
  replaced by the value `memory_order::relaxed`.
1581
 
1582
  ``` cpp
1583
+ constexpr void wait(weak_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
1584
  ```
1585
 
1586
+ *Preconditions:* `order` is `memory_order::relaxed`,
1587
+ `memory_order::acquire`, or `memory_order::seq_cst`.
1588
 
1589
  *Effects:* Repeatedly performs the following steps, in order:
1590
 
1591
  - Evaluates `load(order)` and compares it to `old`.
1592
  - If the two are not equivalent, returns.
 
1596
  *Remarks:* Two `weak_ptr` objects are equivalent if they store the same
1597
  pointer and either share ownership or are both empty. This function is
1598
  an atomic waiting operation [[atomics.wait]].
1599
 
1600
  ``` cpp
1601
+ constexpr void notify_one() noexcept;
1602
  ```
1603
 
1604
  *Effects:* Unblocks the execution of at least one atomic waiting
1605
  operation that is eligible to be unblocked [[atomics.wait]] by this
1606
  call, if any such atomic waiting operations exist.
1607
 
1608
  *Remarks:* This function is an atomic notifying
1609
  operation [[atomics.wait]].
1610
 
1611
  ``` cpp
1612
+ constexpr void notify_all() noexcept;
1613
  ```
1614
 
1615
  *Effects:* Unblocks the execution of all atomic waiting operations that
1616
  are eligible to be unblocked [[atomics.wait]] by this call.
1617