---
title: C++ Standard Library Ready Issues to be moved in Croydon, Mar. 2026
document: P4145R0
date: 2026-03-25
audience: WG21
reply-to:
  - "Jonathan Wakely"
paper-type: proposal
---

# C++ Standard Library Ready Issues to be moved in Croydon, Mar. 2026

| Doc. no. | P4145R0 |
| --- | --- |
| Date: | 2026-03-25 |
| Audience: | WG21 |
| Reply to: | Jonathan Wakely <[lwgchair@gmail.com](mailto:lwgchair@gmail.com)> |

- Ready Issues
  - 2414. Member function reentrancy should be implementation-defined
  - 2746. Inconsistency between requirements for emplace between optional and variant
  - 3504. condition_variable::wait_for is overspecified
  - 3599. The const overload of lazy_split_view::begin should be constrained by const Pattern
  - 4290. Missing *Mandates* clauses on `is_sufficiently_aligned`
  - 4453. atomic_ref<cv T>::required_alignment should be the same as for `T`
  - 4454. `assert` should forbid `co_await` and `co_yield`
  - 4469. Names of parameters of addressable function shall remain unspecified
  - 4472. std::atomic_ref<const T> can be constructed from temporaries
  - 4486. `*integral-constant-like*` and `*constexpr-wrapper-like*` exposition-only concept duplication
  - 4492. `std::generate` and `std::ranges::generate` wording is unclear for parallel algorithms
  - 4496. Precedes vs Reachable in [meta.reflection]
  - 4499. `flat_set::insert_range` specification may be problematic
  - 4510. Ambiguity of `std::ranges::advance` and `std::ranges::next` when the difference type is also a sentinel type
  - 4511. Inconsistency between the deduction guide of `std::mdspan` taking `(data_handle_type, mapping_type, accessor_type)` and the corresponding constructor
  - 4512. The `system_encoded_string()` and `generic_system_encoded_string()` member functions of `std::filesystem::path` are misnamed
  - 4535. Disallow user specialization of `<simd>` templates
  - 4536. Type traits have inconsistent interactions with immediate functions
- Tentatively Ready Issues
  - 3831. Two-digit formatting of negative year is ambiguous
  - 4090. Underspecified use of locale facets for locale-dependent std::format
  - 4130. Preconditions for std::launder might be overly strict
  - 4259. P1148R0 changed the return values of searching functions of `std::basic_string` on some platforms
  - 4324. `unique_ptr<void>::operator*` is not SFINAE-friendly
  - 4378. Inconsistency between `std::basic_string`'s `data()` and `operator[]` specification
  - 4457. freestanding for `stable_sort`, `stable_partition` and `inplace_merge`
  - 4460. Missing *Throws* : for last `variant` constructor
  - 4467. `hive::splice` can throw `bad_alloc`
  - 4468. §[const.wrap.class] "`operator decltype(auto)`" is ill-formed
  - 4474. "`round_to_nearest`" rounding mode is unclear
  - 4477. Placement `operator delete` should be constexpr
  - 4480. <stdatomic.h> should provide `ATOMIC_CHAR8_T_LOCK_FREE`
  - 4481. Disallow chrono::duration<const T, P>
  - 4483. Multidimensional arrays are not supported by meta::reflect_constant_array and related functions
  - 4491. Rename `submdspan_extents` and `submdspan_canonicalize_slices`
  - 4493. Specification for some functions of bit reference types seems missing
  - 4500. `constant_wrapper` wording problems
  - 4514. Missing absolute value of `init` in `vector_two_norm` and `matrix_frob_norm`
  - 4517. `data_member_spec` should throw for *cv* -qualified unnamed bit-fields
  - 4522. Clarify that `std::format` transcodes for `std::wformat_strings`
  - 4523. `constant_wrapper` should assign to `value`
  - 4525. `task` 's `final_suspend` should `move` the result
  - 4527. `await_transform` needs to use `as_awaitable`
  - 4528. `task` needs `get_completion_signatures()`
  - 4529. `task::promise_type::await_transform` declaration and definition mismatch

## Ready Issues

---

### Member function reentrancy should be implementation-defined

**Section:** 16.4.6.9 [[reentrancy]](https://wg21.link/reentrancy) **Status:** [Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Stephan T. Lavavej **Opened:** 2014-07-01 **Last modified:** 2026-02-20

**Priority:**3

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#reentrancy) in [reentrancy].

**Discussion:**

N3936 16.4.6.9 [[reentrancy]](https://wg21.link/reentrancy)/1 talks about "functions", but that doesn't address the scenario of calling different member functions of a single object. Member functions often have to violate and then re-establish invariants. For example, vectors often have "holes" during insertion, and element constructors/destructors/etc. shouldn't be allowed to observe the vector while it's in this invariant-violating state. The [reentrancy] Standardese should be extended to cover member functions, so that implementers can either say that member function reentrancy is universally prohibited, or selectively allowed for very specific scenarios. (For clarity, this issue has been split off from LWG [2382](https://cplusplus.github.io/LWG/lwg-closed.html#2382)<sup>[(i)](https://cplusplus.github.io/LWG/issue2382)</sup>.)

*[2014-11-03 Urbana]*

AJM confirmed with SG1 that they had no special concerns with this issue, and LWG should retain ownership. AM: this is too overly broad as it also covers calling the exact same member function on a different object STL: so you insert into a map, and copying the value triggers another insertion into a different map of the same type GR: reentrancy seems to imply the single-threaded case, but needs to consider the multi-threaded case Needs more wording.

Move to Open

*[2015-07 Telecon Urbana]*

Marshall to ping STL for updated wording.

*[2016-05 email from STL]*

I don't have any better suggestions than my original PR at the moment.

**Previous resolution [SUPERSEDED]:**

> This wording is relative to N3936.
> 
> 1. Change 16.4.6.9 [[reentrancy]](https://wg21.link/reentrancy) p1 as indicated: -1- Except where explicitly specified in this standard, it is implementation-defined which functions <ins>(including different member functions called on a single object)</ins> in the Standard C++ library may be recursively reentered.

*[2021-07-29 Tim suggests new wording]*

The "`this` pointer" restriction is modeled on 11.9.5 [[class.cdtor]](https://wg21.link/class.cdtor) p2. It allows us to continue to specify a member function `f` as calling some other member function `g`, since any such call would use something obtained from the first member function's `this` pointer. In all other cases, this wording disallows such "recursion on object" unless both member functions are `const` (or are treated as such for the purposes of data race avoidance). Using "access" means that we also cover direct access to the object representation, such as the following pathological example [from Arthur O'Dwyer](https://quuxplusone.github.io/blog/2021/04/17/pathological-string-appends/), which is now undefined:

> ```
> std::string s = "hello world";
> char *first = (char*)&s;
> char *last = (char*)(&s + 1);
> s.append(first, last);
> ```

**Previous resolution [SUPERSEDED]:**

> This wording is relative to [N4892](https://wg21.link/N4892).
> 
> 1. Add the following paragraph to 16.4.6.9 [[reentrancy]](https://wg21.link/reentrancy): <ins>-?- During the execution of a standard library non-static member function *F* on an object, if that object is accessed through a glvalue that is not obtained, directly or indirectly, from the `this` pointer of *F*, in a manner that can conflict (6.10.2.2 [[intro.races]](https://wg21.link/intro.races)) with any access that *F* is permitted to perform (16.4.6.10 [[res.on.data.races]](https://wg21.link/res.on.data.races)), the behavior is undefined unless otherwise specified.</ins>

*[2026-02-20; Tim provides new wording]*

Refer to "object parameter" not "`this` pointer".

*[2026-02-20; LWG telecon; Status changed: Open → Ready.]*

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Append the following paragraph to 16.4.6.9 [[reentrancy]](https://wg21.link/reentrancy): <ins>-?- During the execution of a standard library non-static member function *F* on an object, if that object is accessed through a glvalue that is not obtained, directly or indirectly, from the object parameter of *F*, in a manner that can conflict (6.10.2.2 [[intro.races]](https://wg21.link/intro.races)) with any access that *F* is permitted to perform (16.4.6.10 [[res.on.data.races]](https://wg21.link/res.on.data.races)), the behavior is undefined unless otherwise specified.</ins>

---

### Inconsistency between requirements for emplace between optional and variant

**Section:** 22.5.3.4 [[optional.assign]](https://wg21.link/optional.assign), 22.6.3.5 [[variant.mod]](https://wg21.link/variant.mod), 22.7.4.4 [[any.modifiers]](https://wg21.link/any.modifiers) **Status:** [Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Richard Smith **Opened:** 2016-07-13 **Last modified:** 2025-12-05

**Priority:**3

**Discussion:**

Referring to N4604:

In [optional.object.assign]: `emplace` (normal form) has a Requires that the construction works.

> *Requires:* `is_constructible_v<T, Args&&...>` is `true`.

`emplace` (`initializer_list` form) has a SFINAE condition:

> *Remarks:* […] unless `is_constructible_v<T, initializer_list<U>&, Args&&...>` is `true`.

In 22.7.4.4 [[any.modifiers]](https://wg21.link/any.modifiers): `emplace` (normal form) has a Requires that the construction works:

> *Requires:* `is_constructible_v<T, Args...>` is `true`.

`emplace` (`initializer_list` form) has a SFINAE condition:

> *Remarks:* […] unless `is_constructible_v<T, initializer_list<U>&, Args...>` is `true`.

In 22.6.3.5 [[variant.mod]](https://wg21.link/variant.mod): `emplace` (`T`, normal form) has a SFINAE condition:

> *Remarks:* […] unless `is_constructible_v<T, Args...>` is `true`, and `T` occurs exactly once in `Types...`.

`emplace` (Idx, normal form) has a *both* a Requires and a SFINAE condition:

> *Requires:* `I < sizeof...(Types)` *Remarks:* […] unless `is_constructible_v<T, Args...>` is `true`, and `T` occurs exactly once in `Types...`.

`emplace` (`T`, `initializer_list` form) has a SFINAE condition:

> *Remarks:* […] unless `is_constructible_v<T, initializer_list<U>&, Args...>` is `true`, and `T` occurs exactly once in `Types...`.

`emplace` (Idx, `initializer_list` form) has a both a Requires and a SFINAE condition:

> *Requires:* `I < sizeof...(Types)` *Remarks:* […] unless `is_constructible_v<T, Args...>` is true, and `T` occurs exactly once in `Types...`.

Why the inconsistency? Should all the cases have a SFINAE requirement? I see that variant has an additional requirement (`T` occurs exactly once in `Types...`), but that only agues that it must be a SFINAE condition — doesn't say that the other cases (any/variant) should not. `map`/`multimap`/`unordered_map`/`unordered_multimap` have SFINAE'd versions of `emplace` that don't take `initializer_list`s, but they don't have any `emplace` versions that take ILs. Suggested resolution: Add SFINAE requirements to `optional::emplace(Args&&... args)` and `any::emplace(Args&&... args);`

*[2016-08 Chicago]*

During issue prioritization, people suggested that this might apply to `any` as well.

Ville notes that [2746](https://cplusplus.github.io/LWG/lwg-active.html#2746)<sup>[(i)](https://cplusplus.github.io/LWG/issue2746)</sup>, [2754](https://cplusplus.github.io/LWG/lwg-defects.html#2754)<sup>[(i)](https://cplusplus.github.io/LWG/issue2754)</sup> and [2756](https://cplusplus.github.io/LWG/lwg-defects.html#2756)<sup>[(i)](https://cplusplus.github.io/LWG/issue2756)</sup> all go together.

*[2020-05-10; Daniel comments and provides wording]*

The inconsistency between the two `any::emplace` overloads have been removed by resolving LWG [2754](https://cplusplus.github.io/LWG/lwg-defects.html#2754)<sup>[(i)](https://cplusplus.github.io/LWG/issue2754)</sup> to use *Constraints:* elements. The last Mandating paper ([P1460R1](https://wg21.link/p1460r1)), adopted in Prague, changed the *Requires:* elements for `variant::emplace`, "`I < sizeof...(Types)`" to *Mandates:*, but that paper was focused on fixing inappropriate preconditions, not searching for consistency here. Given that the `in_place_index_t` constructors of `variant` uses SFINAE-conditions for this form of static precondition violation, I recommend that its `emplace` functions use the same style, which would bring them also in consistency with their corresponding type-based `emplace` forms that are *Mandates:*-free but delegate to the index-based forms.

**Previous resolution [SUPERSEDED]:**

> This wording is relative to [N4861](https://wg21.link/n4861).
> 
> 1. Modify 22.5.3.4 [[optional.assign]](https://wg21.link/optional.assign), as indicated: template<class... Args> T& emplace(Args&&... args); -29- *<del>Mandates</del><ins>Constraints</ins>:* `is_constructible_v<T, Args...>` is `true`. […] template<class U, class... Args> T& emplace(initializer_list<U> il, Args&&... args); -35- *Constraints:* `is_constructible_v<T, initializer_list<U>&, Args...>` is `true`. […]
> 2. Modify 22.6.3.5 [[variant.mod]](https://wg21.link/variant.mod), as indicated: template<class T, class... Args> T& emplace(Args&&... args); -1- *Constraints:* `is_constructible_v<T, Args...>` is `true`, and `T` occurs exactly once in `Types`. […] template<class T, class U, class... Args> T& emplace(initializer_list<U> il, Args&&... args); -3- *Constraints:* `is_constructible_v<T, initializer_list<U>&, Args...>` is `true`, and `T` occurs exactly once in `Types`. […] template<size_t I, class... Args> variant_alternative_t<I, variant<Types...>>& emplace(Args&&... args); <del>-5- *Mandates:* `I < sizeof...(Types)`.</del> -6- *Constraints:* `is_constructible_v<T<sub>*I*</sub>, Args...>` is `true` <ins>and `I < sizeof...(Types)` is `true`</ins>. […] template<size_t I, class U, class... Args> variant_alternative_t<I, variant<Types...>>& emplace(initializer_list<U> il, Args&&... args); <del>-12- *Mandates:* `I < sizeof...(Types)`.</del> -13- *Constraints:* `is_constructible_v<T<sub>*I*</sub>, initializer_list<U>&, Args...>` is `true` <ins>and `I < sizeof...(Types)` is `true`</ins>. […]

*[2025-12-05; Jonathan provides new wording]*

There's no need to use SFINAE to check if a `variant` with N alternatives allows you to emplace the N+1<sup>th</sup> alternative.

*[2025-12-05; LWG telecon. Moved to Ready]*

**Proposed resolution:**

This wording is relative to [N5014](https://wg21.link/N5014).

1. Modify 22.5.3.4 [[optional.assign]](https://wg21.link/optional.assign), as indicated: template<class... Args> T& emplace(Args&&... args); -29- *<del>Mandates</del><ins>Constraints</ins>:* `is_constructible_v<T, Args...>` is `true`. […] template<class U, class... Args> T& emplace(initializer_list<U> il, Args&&... args); -35- *Constraints:* `is_constructible_v<T, initializer_list<U>&, Args...>` is `true`. […]

---

### condition_variable::wait_for is overspecified

**Section:** 32.7.4 [[thread.condition.condvar]](https://wg21.link/thread.condition.condvar) **Status:** [Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jonathan Wakely **Opened:** 2020-11-18 **Last modified:** 2026-02-20

**Priority:**3

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#thread.condition.condvar) in [thread.condition.condvar].

**Discussion:**

32.7.4 [[thread.condition.condvar]](https://wg21.link/thread.condition.condvar) p24 says:

> *Effects:* Equivalent to: `return wait_until(lock, chrono::steady_clock::now() + rel_time);`

This is overspecification, removing implementer freedom to make `cv.wait_for(duration<float>(1))` work accurately. The type of `steady_clock::now() + duration<float>(n)` is `time_point<steady_clock, duration<float, steady_clock::period>>`. If the steady clock's period is `std::nano` and its epoch is the time the system booted, then in under a second a 32-bit `float` becomes unable to exactly represent those `time_points`! Every second after boot makes `duration<float, nano>` less precise. This means that adding a `duration<float>` to a `time_point` (or `duration`) measured in nanoseconds is unlikely to produce an accurate value. Either it will round down to a value less than `now()`, or round up to one greater than `now() + 1s`. Either way, the `wait_for(rel_time)` doesn't wait for the specified time, and users think the implementation is faulty. A possible solution is to use `steady_clock::now() + ceil<steady_clock::duration>(rel_time)` instead. This converts the relative time to a suitably large integer, and then the addition is not affected by floating-point rounding errors due to the limited precision of 32-bit `float`. Libstdc++ has been doing this for nearly three years. Alternatively, the standard could just say that the relative timeout is converted to an absolute timeout measured against the steady clock, and leave the details to the implementation. Some implementations might not be affected by the problem (e.g. if the steady clock measures milliseconds, or processes only run for a few seconds and use the process start as the steady clock's epoch). This also affects the other overload of `condition_variable::wait_for`, and both overloads of `condition_variable_any::wait_for`.

*[2020-11-29; Reflector prioritization]*

Set priority to 3 during reflector discussions.

*[2024-06-18; Jonathan adds wording]*

**Previous resolution [SUPERSEDED]:**

> This wording is relative to [N4981](https://wg21.link/N4981).
> 
> 1. Modify 32.7.1 [[thread.condition.general]](https://wg21.link/thread.condition.general) as indicated, adding a new paragraph to the end: <ins>-6- The definitions in 32.7 [[thread.condition]](https://wg21.link/thread.condition) make use of the following exposition-only function: </ins> `<ins>template<class Dur> chrono::steady_clock::time_point *rel-to-abs*(const Dur& rel_time) { return chrono::steady_clock::now() + chrono::ceil<chrono::steady_clock::duration>(rel_time); } </ins>`
> 2. Modify 32.7.4 [[thread.condition.condvar]](https://wg21.link/thread.condition.condvar) as indicated: `template<class Rep, class Period> cv_status wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time);` -23- *Preconditions*: `lock.owns_lock()` is `true` and `lock.mutex()` is locked by the calling thread, and either [...] -24- *Effects*: Equivalent to: `return wait_until(lock, <del>chrono::steady_clock::now() + rel_time</del> <ins>*rel-to-abs*(rel_time)</ins>);` [...] `template<class Rep, class Period, class Predicate> cv_status wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred);` -35- *Preconditions*: `lock.owns_lock()` is `true` and `lock.mutex()` is locked by the calling thread, and either [...] -36- *Effects*: Equivalent to: `return wait_until(lock, <del>chrono::steady_clock::now() + rel_time</del> <ins>*rel-to-abs*(rel_time)</ins>, std::move(pred));` [*Note 8*: There is no blocking if `pred()` is initially `true`, even if the timeout has already expired. — *end note*]
> 3. Modify 32.7.5.2 [[thread.condvarany.wait]](https://wg21.link/thread.condvarany.wait) as indicated: `template<class Lock, class Rep, class Period> cv_status wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time);` -11- *Effects*: Equivalent to: `return wait_until(lock, <del>chrono::steady_clock::now() + rel_time</del> <ins>*rel-to-abs*(rel_time)</ins>);` [...] `template<class Lock, class Rep, class Period, class Predicate> cv_status wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred);` -19- *Effects*: Equivalent to: `return wait_until(lock, <del>chrono::steady_clock::now() + rel_time</del> <ins>*rel-to-abs*(rel_time)</ins>, std::move(pred));`

*[2026-02-20; Jonathan provides new wording]*

Need to add another change for the interruptible `wait_for`.

*[2026-02-20; LWG telecon; Status changed: New → Ready.]*

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify 32.7.1 [[thread.condition.general]](https://wg21.link/thread.condition.general) as indicated, adding a new paragraph to the end: <ins>-6- The definitions in 32.7 [[thread.condition]](https://wg21.link/thread.condition) make use of the following exposition-only function: </ins> `<ins>template<class Dur> chrono::steady_clock::time_point *rel-to-abs*(const Dur& rel_time) { return chrono::steady_clock::now() + chrono::ceil<chrono::steady_clock::duration>(rel_time); } </ins>`
2. Modify 32.7.4 [[thread.condition.condvar]](https://wg21.link/thread.condition.condvar) as indicated: `template<class Rep, class Period> cv_status wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time);` -23- *Preconditions*: `lock.owns_lock()` is `true` and `lock.mutex()` is locked by the calling thread, and either [...] -24- *Effects*: Equivalent to: `return wait_until(lock, <del>chrono::steady_clock::now() + rel_time</del> <ins>*rel-to-abs*(rel_time)</ins>);` [...] `template<class Rep, class Period, class Predicate> cv_status wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred);` -35- *Preconditions*: `lock.owns_lock()` is `true` and `lock.mutex()` is locked by the calling thread, and either [...] -36- *Effects*: Equivalent to: `return wait_until(lock, <del>chrono::steady_clock::now() + rel_time</del> <ins>*rel-to-abs*(rel_time)</ins>, std::move(pred));` [*Note 8*: There is no blocking if `pred()` is initially `true`, even if the timeout has already expired. — *end note*]
3. Modify 32.7.5.2 [[thread.condvarany.wait]](https://wg21.link/thread.condvarany.wait) as indicated: `template<class Lock, class Rep, class Period> cv_status wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time);` -11- *Effects*: Equivalent to: `return wait_until(lock, <del>chrono::steady_clock::now() + rel_time</del> <ins>*rel-to-abs*(rel_time)</ins>);` [...] `template<class Lock, class Rep, class Period, class Predicate> cv_status wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred);` -19- *Effects*: Equivalent to: `return wait_until(lock, <del>chrono::steady_clock::now() + rel_time</del> <ins>*rel-to-abs*(rel_time)</ins>, std::move(pred));`
4. Modify 32.7.5.3 [[thread.condvarany.intwait]](https://wg21.link/thread.condvarany.intwait) as indicated: `template<class Lock, class Rep, class Period, class Predicate> bool wait_for(Lock& lock, stop_token stoken, const chrono::duration<Rep, Period>& rel_time, Predicate pred);` -13- *Effects*: Equivalent to: `return wait_until(lock, std::move(stoken), <del>chrono::steady_clock::now() + rel_time</del> <ins>*rel-to-abs*(rel_time)</ins>, std::move(pred));`

---

### The const overload of lazy_split_view::begin should be constrained by const Pattern

**Section:** 25.7.16.2 [[range.lazy.split.view]](https://wg21.link/range.lazy.split.view) **Status:** [Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Hewill Kang **Opened:** 2021-09-23 **Last modified:** 2026-01-16

**Priority:**3

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#range.lazy.split.view) in [range.lazy.split.view].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#range.lazy.split.view) in [range.lazy.split.view].

**Discussion:**

Consider the following code snippet:

> ```
> #include <ranges>
> 
> int main() {
>   auto p = std::views::iota(0)
>          | std::views::take(1)
>          | std::views::reverse;
>   auto r = std::views::single(42)
>          | std::views::lazy_split(p);
>   auto f = r.front();
> }
> ```

`r.front()` is ill-formed even if `r` is a `forward_range`.

This is because the `const` overload of `lazy_split_view::begin` is not constrained by the `const Pattern`, which makes it still well-formed in such cases. When the `const` overload of `view_interface<lazy_split_view<V, Pattern>>::front` is instantiated, the `subrange{parent_->pattern_}` inside `lazy_split_view::*outer-iterator*<true>::operator++()` will cause a hard error since `const Pattern` is not a `range`.

*[2021-09-24; Daniel comments]*

This issue is related to LWG [3592](https://cplusplus.github.io/LWG/lwg-defects.html#3592)<sup>[(i)](https://cplusplus.github.io/LWG/issue3592)</sup>.

*[2021-10-14; Reflector poll]*

Set priority to 3 after reflector poll.

*[2026-01-16; LWG telecon. Move to Ready]*

**Proposed resolution:**

This wording is relative to [N4892](https://wg21.link/n4892).

1. Modify 25.7.16.2 [[range.lazy.split.view]](https://wg21.link/range.lazy.split.view), class template `lazy_split_view` synopsis, as indicated: namespace std::ranges { […] template<input_range V, forward_range Pattern> requires view<V> && view<Pattern> && indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> && (forward_range<V> || *tiny-range*<Pattern>) class lazy_split_view : public view_interface<lazy_split_view<V, Pattern>> { private: […] public: […] constexpr auto begin() { […] } constexpr auto begin() const requires forward_range<V> && forward_range<const V> <ins>&& forward_range<const Pattern></ins>{ return *outer-iterator*<true>{*this, ranges::begin(*base_*)}; } constexpr auto end() requires forward_range<V> && common_range<V> { […] } constexpr auto end() const { if constexpr (forward_range<V> && forward_range<const V> && common_range<const V> <ins>&& forward_range<const Pattern></ins>) return *outer-iterator*<true>{*this, ranges::end(*base_*)}; else return default_sentinel; } }; […] }

---

### Missing Mandates clauses on is_sufficiently_aligned

**Section:** 20.2.5 [[ptr.align]](https://wg21.link/ptr.align) **Status:** [Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Damien Lebrun-Grandie **Opened:** 2025-07-03 **Last modified:** 2026-01-30

**Priority:**2

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#ptr.align) in [ptr.align].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#ptr.align) in [ptr.align].

**Discussion:**

`is_sufficiently_aligned` should mandate that the alignment template argument is a power of two and that it is greater equal to the byte alignment of its type template argument. In 20.2.5 [[ptr.align]](https://wg21.link/ptr.align) `is_sufficiently_aligned` has no *Mandates* element. It is an oversight that we realized when implementing [P2897R7](https://wg21.link/P2897R7) into libc++ (in [https://github.com/llvm/llvm-project/pull/122603](https://github.com/llvm/llvm-project/pull/122603)). The function template was originally proposed as a static member function of the `aligned_accessor` class template which has these two *Mandates* clauses and therefore applied (see 23.7.3.5.4.1 [[mdspan.accessor.aligned.overview]](https://wg21.link/mdspan.accessor.aligned.overview) p1). It revision [P2897R4](https://wg21.link/P2897R4), `is_sufficiently_aligned` was moved out the class template definition to become the free function memory helper that was voted into C++26 but the *Mandates* were lost in the process. We propose to correct that oversight and reintroduce the following *Mandates* clauses right above 20.2.5 [[ptr.align]](https://wg21.link/ptr.align) p10.

*[2025-10-23; Reflector poll.]*

Set priority to 2 after reflector poll.

The *Mandates* of `Alignment >= alignof(T)` was put into question, as being too restrictive for general purpose free function.

**Previous resolution [SUPERSEDED]:**

> This wording is relative to [N5008](https://wg21.link/N5008).
> 
> 1. Modify 20.2.5 [[ptr.align]](https://wg21.link/ptr.align) as indicated: template<size_t Alignment, class T> bool is_sufficiently_aligned(T* ptr); <ins>-?- *Mandates*:</ins> <ins>(?.1) — `Alignment` is a power of two, and</ins> <ins>(?.2) — `Alignment >= alignof(T)` is `true`.</ins> -10- *Preconditions*: `p` points to an object `X` of a type similar (7.3.6 [[conv.qual]](https://wg21.link/conv.qual)) to `T`. -11- *Returns*: `true` if `X` has alignment at least `Alignment`, otherwise `false`. -12- *Throws*: Nothing.

*[2026-01-30; Jonathan provides new wording]*

*[2026-01-30; LWG telecon. Status → Ready.]*

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify 20.2.5 [[ptr.align]](https://wg21.link/ptr.align) as indicated: template<size_t Alignment, class T> bool is_sufficiently_aligned(T* ptr); <ins>-?- *Mandates*: `Alignment` is a power of two.</ins> -10- *Preconditions*: `p` points to an object `X` of a type similar (7.3.6 [[conv.qual]](https://wg21.link/conv.qual)) to `T`. -11- *Returns*: `true` if `X` has alignment at least `Alignment`, otherwise `false`. -12- *Throws*: Nothing.

---

### atomic_ref<cv T>::required_alignment should be the same as for T

**Section:** 32.5.7.2 [[atomics.ref.ops]](https://wg21.link/atomics.ref.ops) **Status:** [New](https://cplusplus.github.io/LWG/lwg-active.html#New) **Submitter:** Jonathan Wakely **Opened:** 2025-11-06 **Last modified:** 2026-02-27

**Priority:**2

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#atomics.ref.ops) in [atomics.ref.ops].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#atomics.ref.ops) in [atomics.ref.ops].

**Discussion:**

When [P3323R1](https://wg21.link/P3323R1) fixed support for `atomic_ref<cv T>` we didn't consider that an implementation could define `required_alignment` to be different from `atomic_ref<T>::required_alignment`. For example, a processor could support atomic loads on any `int` object, but could require a greater alignment for atomic stores (and read-modify-write and modify-write operations). So the `required_alignment` could be `alignof(int)` for `const int` but `2 * alignof(int)` for `int`, because the latter is needed for stores.

A malicious implementation could even define `required_alignment` to be greater for the `const T` specialization, which would make it undefined to use the new converting constructor added by [P3860R1](https://wg21.link/P3860R1).

We should constrain implementations to use the same `required_alignment` for cv `T`, so that users can use `atomic_ref<const T>` on any object that is referenced by a `atomic_ref<T>`.

*[2026-01-16; Reflector poll.]*

Set priority to 2 after reflector poll.

"Should be broaded to include all similar types, not just top-level *cv*."

"Should we have the same guarantee for `is_always_lock_free`? Would allow checking if `atomic<volatile T>` is usable by checking `atomic<T>`."

**Previous resolution [SUPERSEDED]:**

> This wording is relative to [N5014](https://wg21.link/N5014).
> 
> 1. Modify [atomics.refs.ops], as indicated: static constexpr size_t required_alignment; -1- The alignment required for an object to be referenced by an atomic reference, which is at least `alignof(T)`. <ins> The value of `required_alignment` is the same as `atomic_ref<remove_cv_t<T>>::required_alignment` </ins> -2- [*Note 1*: Hardware could require an object referenced by an `atomic_ref` to have stricter alignment (6.8.3 [[basic.align]](https://wg21.link/basic.align)) than other objects of type `T`. Further, whether operations on an `atomic_ref` are lock-free could depend on the alignment of the referenced object. For example, lock-free operations on `std::complex<double>` could be supported only if aligned to `2*alignof(double)`. — *end note*]

*[2026-02-16; Tomasz provides updated resolution.]*

Guarantee that `required_alignment` and `is_always_lock_free` values are the same for any similar types.

We define equality to `atomic_ref<remove_cv_t<U>`, as `volatile` atomics may be ill-formed.

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify [atomics.refs.ops], as indicated: static constexpr size_t required_alignment; -1- The alignment required for an object to be referenced by an atomic reference, which is at least `alignof(T)`. <ins> For any type `U` similar to `T`, the value of `required_alignment` is the same as `atomic_ref<remove_cv_t<U>>::required_alignment`. </ins> -2- [*Note 1*: Hardware could require an object referenced by an `atomic_ref` to have stricter alignment (6.8.3 [[basic.align]](https://wg21.link/basic.align)) than other objects of type `T`. Further, whether operations on an `atomic_ref` are lock-free could depend on the alignment of the referenced object. For example, lock-free operations on `std::complex<double>` could be supported only if aligned to `2*alignof(double)`. — *end note*] static constexpr bool is_always_lock_free; -3- The static data member `is_always_lock_free` is `true` if the `atomic_ref` type's operations are always lock-free, and false otherwise. <ins>For any type `U` similar to `T` the value of `is_always_lock_free` is the same as `atomic_ref<remove_cv_t<U>>::is_always_lock_free`.</ins>

---

### assert should forbid co_await and co_yield

**Section:** 19.3.3 [[assertions.assert]](https://wg21.link/assertions.assert) **Status:** [Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jonathan Wakely **Opened:** 2025-11-06 **Last modified:** 2026-03-06

**Priority:**1

**Discussion:**

Addresses [GB 05-129](https://github.com/cplusplus/nbballot/issues/708)

The new implementation of `assert` introduced by [P2264R7](https://wg21.link/P2264R7) might require something like `sizeof(bool(__VA_ARGS__))`. Using something like `assert((co_yield 1, true))` would be ill-formed if the implementation of `assert` uses `sizeof`, because `co_yield` cannot appear in an unevaluated context.

The specification for `assert` should forbid using any constructs which are not valid in unevaluated contexts, unless we are certain that the new `assert` requirements can be implemented without such tricks using unevaluated contexts. "Ill-formed; no diagnostic required" seems appropriate.

*[2026-03-06 Tim provides wording]*

*[2026-03-06 LWG telecon; move to Ready]*

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

Modify 19.3.3 [[assertions.assert]](https://wg21.link/assertions.assert) as indicated: -3- If `__VA_ARGS__` does not expand to <del>an</del><ins>a well-formed</ins> *assignment-expression*, the program is ill-formed. <ins>If such an *assignment-expression* is ill-formed when treated as an unevaluated operand (7.6.2.4 [[expr.await]](https://wg21.link/expr.await), 7.6.17 [[expr.yield]](https://wg21.link/expr.yield)), the program is ill-formed, no diagnostic required.</ins>

---

### Names of parameters of addressable function shall remain unspecified

**Section:** 16.4.5.2.1 [[namespace.std]](https://wg21.link/namespace.std) **Status:** [Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Tomasz Kamiński **Opened:** 2025-11-14 **Last modified:** 2026-01-16

**Priority:**2

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#namespace.std) in [namespace.std].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#namespace.std) in [namespace.std].

**Discussion:**

The wording in 16.4.5.2.1 [[namespace.std]](https://wg21.link/namespace.std) p7 guarantees that reflection of the addressable function can be reliably produced. With the addition of the function parameter name, it is possible to access the parameter name of such functions:

```
constexpr auto p = parameters_of(^^std::endl)[0];
static_assert( identifier_of(p) == "os" ); // guaranteed?
```

We should clarify that parameter names used by standard library implementation remain unspecified, by making result of `has_identifier` and `identifier_of` unspecified on reflection of such parameter.

*[2026-01-16; Reflector poll.]*

Set priority to 2 after reflector poll.

*[2026-01-16; LWG telecon. Move to Ready]*

**Proposed resolution:**

This wording is relative to [N5014](https://wg21.link/N5014).

1. Modify 16.4.5.2.1 [[namespace.std]](https://wg21.link/namespace.std), as indicated: Let *F* denote a standard library function or function template. Unless *F* is designated an addressable function, it is unspecified if or how a reflection value designating the associated entity can be formed. <ins>For any value `*p*` of type `meta::info` that represents a reflection of a parameter of *F*, it is unspecified if `has_identifier(*p*)` returns `true` or `false`, and if `meta::has_identifier(*p*)` is `true`, then the `NTMBS` produced by `meta::identifier_of(*p*)` and `meta::u8identifier_of(*p*)` is unspecified.</ins>

---

### std::atomic_ref<const T> can be constructed from temporaries

**Section:** 32.5.7 [[atomics.ref.generic]](https://wg21.link/atomics.ref.generic) **Status:** [Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jiang An **Opened:** 2025-11-11 **Last modified:** 2025-12-05

**Priority:**Not Prioritized

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#atomics.ref.generic) in [atomics.ref.generic].

**Discussion:**

`std::atomic_ref<T>` has a constructor taking `T&`, so when `T` is a `const` but not `volatile` object type, the constructor parameter can be bound to a temporary expression, which doesn't seem to make sense. Even after [P3860R1](https://wg21.link/P3860R1), explicitly constructing `std::atomic_ref<const T>` from `std::atomic_ref<volatile T>` can be well-formed with the undesired semantics when it is well-formed to instantiate `std::atomic_ref<volatile T>` and its operator `T` conversion function, because the construction calls the conversion function and creates a temporary object. Probably it's better to disallow such reference binding.

*[2025-12-05; LWG telecon. Moved to Ready]*

**Proposed resolution:**

This wording is relative to [N5014](https://wg21.link/N5014) after application of [P3860R1](https://wg21.link/P3860R1).

> [*Drafting note*: The deleted overloads were mirrored from the design of `reference_wrapper` before LWG [2993](https://cplusplus.github.io/LWG/lwg-defects.html#2993)<sup>[(i)](https://cplusplus.github.io/LWG/issue2993)</sup>. As these overloads don't participate in implicit conversion, I don't think there will be any similar issue introduced.]

1. Modify 32.5.7.1 [[atomics.ref.generic.general]](https://wg21.link/atomics.ref.generic.general), primary class template `atomic_ref` synopsis, as indicated: namespace std { template<class T> struct atomic_ref { private: T* ptr; *// exposition only* public: […] constexpr explicit atomic_ref(T&); <ins>explicit atomic_ref(T&&) = delete;</ins> constexpr atomic_ref(const atomic_ref&) noexcept; template<class U> constexpr atomic_ref(const atomic_ref<U>&) noexcept; […] }; }
2. Modify 32.5.7.3 [[atomics.ref.int]](https://wg21.link/atomics.ref.int), class template `atomic_ref` `*integral-type*` specialization synopsis, as indicated: namespace std { template<> struct atomic_ref<*integral-type*> { private: *integral-type** ptr; *// exposition only* public: […] constexpr explicit atomic_ref(*integral-type*&); <ins>explicit atomic_ref(*integral-type*&&) = delete;</ins> constexpr atomic_ref(const atomic_ref&) noexcept; template<class U> constexpr atomic_ref(const atomic_ref<U>&) noexcept; […] }; }
3. Modify 32.5.7.4 [[atomics.ref.float]](https://wg21.link/atomics.ref.float), class template `atomic_ref` `*floating-point-type*` specialization synopsis, as indicated: namespace std { template<> struct atomic_ref<*floating-point-type*> { private: *floating-point-type** ptr; *// exposition only* public: […] constexpr explicit atomic_ref(*floating-point-type*&); <ins>explicit atomic_ref(*floating-point-type*&&) = delete;</ins> constexpr atomic_ref(const atomic_ref&) noexcept; template<class U> constexpr atomic_ref(const atomic_ref<U>&) noexcept; […] }; }
4. Modify 32.5.7.5 [[atomics.ref.pointer]](https://wg21.link/atomics.ref.pointer), class template `atomic_ref` `*pointer-type*` specialization synopsis, as indicated: namespace std { template<> struct atomic_ref<*pointer-type*> { private: *pointer-type** ptr; *// exposition only* public: […] constexpr explicit atomic_ref(*pointer-type*&); <ins>explicit atomic_ref(*pointer-type*&&) = delete;</ins> constexpr atomic_ref(const atomic_ref&) noexcept; template<class U> constexpr atomic_ref(const atomic_ref<U>&) noexcept; […] }; }

---

### *integral-constant-like* and *constexpr-wrapper-like* exposition-only concept duplication

**Section:** 23.7.2.1 [[span.syn]](https://wg21.link/span.syn), 29.10.2 [[simd.expos]](https://wg21.link/simd.expos) **Status:** [Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jonathan Wakely **Opened:** 2025-12-12 **Last modified:** 2025-12-12

**Priority:**Not Prioritized

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#span.syn) in [span.syn].

**Discussion:**

Addresses [US 151-242](https://github.com/cplusplus/nbballot/issues/814)

NB comment: We have two exposition-only concepts for similar things (*`integral-constant-like`* and *`constant-wrapper-like`*). The former can be expressed in terms of the latter. Proposed change: Move *`constant-wrapper-like`* to the library introduction and update *`integral-constant-like`* to use it.

*[2025-12-12; LWG telecon; Status changed: New → Ready.]*

**Proposed resolution:**

This wording is relative to [N5014](https://wg21.link/N5014).

1. Modify 16.3.3.2 [[expos.only.entity]](https://wg21.link/expos.only.entity) by moving the concept (unchanged) from 29.10.2 [[simd.expos]](https://wg21.link/simd.expos): `template<class T, class U = T> using *synth-three-way-result* = *// exposition only* decltype(synth-three-way(declval<T&>(), declval<U&>())); <ins> template<class T> concept *constexpr-wrapper-like* = *// exposition only* convertible_to<T, decltype(T::value)> && equality_comparable_with<T, decltype(T::value)> && bool_constant<T() == T::value>::value && bool_constant<static_cast<decltype(T::value)>(T()) == T::value>::value;</ins> }`
2. Modify 23.7.2.1 [[span.syn]](https://wg21.link/span.syn) as indicated: `template<class T> concept *integral-constant-like* = *// exposition only* is_integral_v<remove_cvref_t<decltype(T::value)>> && !is_same_v<bool, remove_const_t<decltype(T::value)>> && <ins> *constexpr-wrapper-like*<T>;</ins> <del> convertible_to<T, decltype(T::value)> && equality_comparable_with<T, decltype(T::value)> && bool_constant<T() == T::value>::value && bool_constant<static_cast<decltype(T::value)>(T()) == T::value>::value;</del>`
3. Modify 29.10.2 [[simd.expos]](https://wg21.link/simd.expos) as indicated: `<del>template<class T> concept *constexpr-wrapper-like* = *// exposition only* convertible_to<T, decltype(T::value)> && equality_comparable_with<T, decltype(T::value)> && bool_constant<T() == T::value>::value && bool_constant<static_cast<decltype(T::value)>(T()) == T::value>::value;</del>`

---

### std::generate and std::ranges::generate wording is unclear for parallel algorithms

**Section:** 26.7.7 [[alg.generate]](https://wg21.link/alg.generate) **Status:** [Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Ruslan Arutyunyan **Opened:** 2025-12-12 **Last modified:** 2026-01-30

**Priority:**2

**Discussion:**

`std::generate` and `std::ranges::generate` are confusing for parallel algorithms. For both of those *Effects* says "Assigns the result of successive evaluations of `gen()` through each iterator in the range `[first, first + N)`." The word "successive" is confusing when we talk about parallelism. This wording was the preexisting one; [P3179](https://wg21.link/P3179) "Parallel Range Algorithms" didn't modify that, so the problem existed even before. Another problem is that there is nothing about what is allowed to do with the `Generator` template parameter type for C++17 parallel `generate`. Intel, NVIDIA, and GNU libstdc++ implementations do multiple copies of `Generator` object to maximize parallelism, while it's not technically allowed if I am reading the standard correctly. But without `Generator` being copyable we have point of contention and extra synchronization (or we put synchronization part as users' responsibility, which is also not obvious). There is no clear solution right away. We could try to fix the wording for both ranges and C++17 parallel generate but it seems like it requires extra effort because we need to at least verify the new behavior with LLVM libc++ implementation if we want to make `Generator` copyable; libc++ currently does not create per-thread copy of `gen` object. Perhaps, the best strategy for now is to remove `ranges::generate` and `ranges::generate_n` and return them back in C++29 time frame when we figure out the proper fix.

*[2026-01-16; Reflector poll.]*

Set priority to 2 after reflector poll.

*[2026-01-30; LWG telecon. Status → Ready.]*

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify 26.4 [[algorithm.syn]](https://wg21.link/algorithm.syn), header `<algorithm>` synopsis, as indicated: […] *// 26.7.7 [[alg.generate]](https://wg21.link/alg.generate), generate* template<class ForwardIterator, class Generator> constexpr void generate(ForwardIterator first, ForwardIterator last, Generator gen); template<class ExecutionPolicy, class ForwardIterator, class Generator> void generate(ExecutionPolicy&& exec, *// freestanding-deleted, see 26.3.5 [[algorithms.parallel.overloads]](https://wg21.link/algorithms.parallel.overloads)* ForwardIterator first, ForwardIterator last, Generator gen); template<class OutputIterator, class Size, class Generator> constexpr OutputIterator generate_n(OutputIterator first, Size n, Generator gen); template<class ExecutionPolicy, class ForwardIterator, class Size, class Generator> ForwardIterator generate_n(ExecutionPolicy&& exec, *// freestanding-deleted, see 26.3.5 [[algorithms.parallel.overloads]](https://wg21.link/algorithms.parallel.overloads)* ForwardIterator first, Size n, Generator gen); namespace ranges { template<input_or_output_iterator O, sentinel_for<O> S, copy_constructible F> requires invocable<F&> & indirectly_writable<O, invoke_result_t<F&>> constexpr O generate(O first, S last, F gen); template<class R, copy_constructible F> requires invocable<F&> & output_range<R, invoke_result_t<F&>> constexpr borrowed_iterator_t<R> generate(R&& r, F gen); template<input_or_output_iterator O, copy_constructible F> requires invocable<F&> & indirectly_writable<O, invoke_result_t<F&>> constexpr O generate_n(O first, iter_difference_t<O> n, F gen); <del>template<*execution-policy* Ep, random_access_iterator O, sized_sentinel_for<O> S, copy_constructible F> requires invocable<F&> & indirectly_writable<O, invoke_result_t<F&>> O generate(Ep&& exec, O first, S last, F gen); *// freestanding-deleted* template<*execution-policy* Ep, *sized-random-access-range* R, copy_constructible F> requires invocable<F&> & indirectly_writable<iterator_t<R>, invoke_result_t<F&>> borrowed_iterator_t<R> generate(Ep&& exec, R&& r, F gen); *// freestanding-deleted* template<*execution-policy* Ep, random_access_iterator O, copy_constructible F> requires invocable<F&> & indirectly_writable<O, invoke_result_t<F&>> O generate_n(Ep&& exec, O first, iter_difference_t<O> n, F gen); *// freestanding-deleted*</del> } […]
2. Modify 26.7.7 [[alg.generate]](https://wg21.link/alg.generate) as indicated: template<class ForwardIterator, class Generator> constexpr void generate(ForwardIterator first, ForwardIterator last, Generator gen); template<class ExecutionPolicy, class ForwardIterator, class Generator> void generate(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Generator gen); template<class OutputIterator, class Size, class Generator> constexpr OutputIterator generate_n(OutputIterator first, Size n, Generator gen); template<class ExecutionPolicy, class ForwardIterator, class Size, class Generator> ForwardIterator generate_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, Generator gen); template<input_or_output_iterator O, sentinel_for<O> S, copy_constructible F> requires invocable<F&> & indirectly_writable<O, invoke_result_t<F&>> constexpr O ranges::generate(O first, S last, F gen); template<class R, copy_constructible F> requires invocable<F&> & output_range<R, invoke_result_t<F&>> constexpr borrowed_iterator_t<R> ranges::generate(R&& r, F gen); template<input_or_output_iterator O, copy_constructible F> requires invocable<F&> & indirectly_writable<O, invoke_result_t<F&>> constexpr O ranges::generate_n(O first, iter_difference_t<O> n, F gen); <del>template<*execution-policy* Ep, random_access_iterator O, sized_sentinel_for<O> S, copy_constructible F> requires invocable<F&> & indirectly_writable<O, invoke_result_t<F&>> O ranges::generate(Ep&& exec, O first, S last, F gen); template<*execution-policy* Ep, *sized-random-access-range* R, copy_constructible F> requires invocable<F&> & indirectly_writable<iterator_t<R>, invoke_result_t<F&>> borrowed_iterator_t<R> ranges::generate(Ep&& exec, R&& r, F gen); template<*execution-policy* Ep, random_access_iterator O, copy_constructible F> requires invocable<F&> & indirectly_writable<O, invoke_result_t<F&>> O ranges::generate_n(Ep&& exec, O first, iter_difference_t<O> n, F gen);</del> -1- Let `*N*` be `max(0, n)` for the `generate_n` algorithms, and `last - first` for the `generate` algorithms. […]

---

### Precedes vs Reachable in [meta.reflection]

**Section:** 21.4 [[meta.reflection]](https://wg21.link/meta.reflection) **Status:** [Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Daniel Katz **Opened:** 2025-12-11 **Last modified:** 2026-02-20

**Priority:**2

**Discussion:**

Discussion on the [Core mailing list](https://lists.isocpp.org/core/2025/12/19003.php) surfaced a handful of places in 21.4 [[meta.reflection]](https://wg21.link/meta.reflection) that use the "precedes" relation (defined in 6.5 [[basic.lookup]](https://wg21.link/basic.lookup) and primarily used for name lookup) when the "reachable" relation (defined in 10.7 [[module.reach]](https://wg21.link/module.reach)) is really what we want.

*[2026-02-18; Reflector poll.]*

Set priority to 2 after reflector poll.

*[2026-02-20; LWG telecon; Status changed: New → Ready.]*

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify 21.4.6 [[meta.reflection.names]](https://wg21.link/meta.reflection.names) as indicated: consteval bool has_identifier(info r); -1- *Returns*: (1.1) — […] […] (1.8) — Otherwise, if `r` represents the parameter `*P*` of a function `*F*`, then let `*S*` be the set of declarations, ignoring any explicit instantiations, that <del>precede some</del><ins>are reachable from a</ins> point in the evaluation context and that declare either `*F*` or a templated function of which `*F*` is a specialization; […] […] consteval string_view identifier_of(info r); consteval u8string_view u8identifier_of(info r); -2- Let `*E*` be UTF-8 for `u8identifier_of`, and otherwise the ordinary literal encoding. -3- *Returns*: An ntmbs, encoded with `*E*`, determined as follows: (3.1) — […] (3.2) — […] (3.3) — Otherwise, if `r` represents the parameter `*P*` of a function `*F*`, then let `*S*` be the set of declarations, ignoring any explicit instantiations, that <del>precede some</del><ins>are reachable from a</ins> point in the evaluation context and that declare either `*F*` or a templated function of which `*F*` is a specialization; the name that was introduced by a declaration in `*S*` for the parameter corresponding to `*P*`. […]
2. Modify 21.4.7 [[meta.reflection.queries]](https://wg21.link/meta.reflection.queries) as indicated: consteval info type_of(info r); -2- *Returns*: (2.1) — […] […] (2.4) — Otherwise, if `r` represents an enumerator `*N*` of an enumeration `*E*`, then: (2.4.1) — If `*E*` is defined by a declaration `*D*` that <del>precedes</del><ins>is reachable from</ins> a point `*P*` in the evaluation context and `*P*` does not occur within an *enum-specifier* of `*D*`, then a reflection of `*E*`. (2.4.2) — Otherwise, a reflection of the type of `*N*` prior to the closing brace of the *enum-specifier* as specified in 9.8.1 [[dcl.enum]](https://wg21.link/dcl.enum). […] […] consteval bool has_default_argument(info r); -41- *Returns*: If `r` represents a parameter `*P*` of a function `*F*`, then: (41.1) — If `*F*` is a specialization of a templated function `*T*`, then `true` if there exists a declaration `*D*` of `*T*` that <del>precedes some</del><ins>is reachable from a</ins> point in the evaluation context and `*D*` specifies a default argument for the parameter of `*T*` corresponding to `*P*`. Otherwise, `false`. (41.2) — Otherwise, if there exists a declaration `*D*` of `*F*` that <del>precedes some</del><ins>is reachable from a</ins> point in the evaluation context and `*D*` specifies a default argument for `*P*`, then `true`.
3. Modify 21.4.18 [[meta.reflection.annotation]](https://wg21.link/meta.reflection.annotation) as indicated: consteval vector<info> annotations_of(info item); -1- Let `*E*` be […] -2- *Returns*: A `vector` containing all of the reflections `*R*` representing each annotation applying to each declaration of `*E*` that <del>precedes</del><ins>is reachable from</ins> either <del>some</del><ins>a</ins> point in the evaluation context (7.7 [[expr.const]](https://wg21.link/expr.const)) or a point immediately following the *class-specifier* of the outermost class for which such a point is in a complete-class context. […]

---

### flat_set::insert_range specification may be problematic

**Section:** 23.6.11.5 [[flat.set.modifiers]](https://wg21.link/flat.set.modifiers), 23.6.12.5 [[flat.multiset.modifiers]](https://wg21.link/flat.multiset.modifiers) **Status:** [Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Hewill Kang **Opened:** 2025-12-22 **Last modified:** 2026-02-20

**Priority:**2

**Discussion:**

The function adds elements via:

> ```
> ranges::for_each(rg, [&](auto&& e) {
>   c.insert(c.end(), std::forward<decltype(e)>(e));
> });
> ```

Here, `e` is an element of the input range. However, this can lead to ambiguity when `e` can also be converted to `initializer_list`, as `vector::insert` has an overload of `insert(const_iterator, initializer_list<T>)`.

*[2026-02-18; Reflector poll.]*

Set priority to 2 after reflector poll.

Pessimizing a very common case (matching type), for uncommon one.

*[2026-02-20; LWG telecon; Status changed: New → Ready.]*

Implementations can optimize away the extra move for the case where the range's value type is already the same as the flat set's value type.

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify 23.6.11.5 [[flat.set.modifiers]](https://wg21.link/flat.set.modifiers) as indicated: template<*container-compatible-range*<value_type> R> constexpr void insert_range(R&& rg); -10- *Effects*: Adds elements to `*c*` as if by: ranges::for_each(rg, [&](<ins>value_type</ins><del>auto&&</del> e) { *c*.insert(*c*.end(), <ins>std::move</ins><del>std::forward<decltype(e)></del>(e)); });
2. Modify 23.6.12.5 [[flat.multiset.modifiers]](https://wg21.link/flat.multiset.modifiers) as indicated: template<*container-compatible-range*<value_type> R> void insert_range(R&& rg); -9- *Effects*: Adds elements to `*c*` as if by: ranges::for_each(rg, [&](<ins>value_type</ins><del>auto&&</del> e) { *c*.insert(*c*.end(), <ins>std::move</ins><del>std::forward<decltype(e)></del>(e)); });

---

### Ambiguity of std::ranges::advance and std::ranges::next when the difference type is also a sentinel type

**Section:** 24.4.4.2 [[range.iter.op.advance]](https://wg21.link/range.iter.op.advance), 24.4.4.4 [[range.iter.op.next]](https://wg21.link/range.iter.op.next) **Status:** [Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jiang An **Opened:** 2026-01-09 **Last modified:** 2026-02-27

**Priority:**3

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#range.iter.op.advance) in [range.iter.op.advance].

**Discussion:**

Currently, `ranges::advance` and `ranges::next` have `operator()` overloads that accept `(iterator, sentinel)` and `(iterator, difference)`. However, when the difference type of the iterator is also a sentinel type, there may be ambiguity in both overloads. E.g. the following example is rejected when compiling with libc++ or libstdc++ ([demo](https://godbolt.org/z/z3rPEhjjs)):

> ```
> #include <cstddef>
> #include <iterator>
> #include <type_traits>
> 
> template<class T>
> struct FwdIter { // triggers ADL for T
>   FwdIter();
> 
>   using value_type      = std::remove_cv_t<T>;
>   using difference_type = int;
> 
>   T& operator*() const;
> 
>   FwdIter& operator++();
>   FwdIter operator++(int);
> 
>   friend bool operator==(const FwdIter&, const FwdIter&);
> };
> 
> static_assert(std::forward_iterator<FwdIter<int>>);
> 
> struct OmniConv {
>   OmniConv(const auto&);
>   friend bool operator==(OmniConv, OmniConv); // found by ADL via things related to OmniConv
> };
> 
> int main() {
>   FwdIter<OmniConv> it{};
>   std::ranges::advance(it, 0); // ambiguous
>   std::ranges::next(it, 0); // ambiguous
> }
> ```

Perhaps it would be better to ensure that calling `ranges::advance` or `ranges::next` with an iterator value and a value of the difference type is unambiguous. Note that wrapping iterators that trigger ADL for the value type like the `FwdIter` in this example are common in standard library implementations, so ambiguity can be easily raised from containers with such `OmniConv` being their element type.

*[2026-02-20; Reflector poll.]*

Set priority to 3 after reflector poll.

The type in the example is basically a `std::any` that additionally type-erases equality. That causes a problem for templated iterators that have their value type's namespace as an associated namespace for ADL.

Instead of allowing integers to be sentinels in general but just restricting them from being used with these overloads, we could just change the concept so that integers do not model `sentinel_for`. That's similar to what we did for `span`'s constructor which has a similar problem (though that one's more aggressive due to compatibility constraints).

**Previous resolution [SUPERSEDED]:**

> This wording is relative to [N5032](https://wg21.link/N5032).
> 
> 1. Modify 24.2 [[iterator.synopsis]](https://wg21.link/iterator.synopsis), header `<iterator>` synopsis, as indicated: […] namespace std { template<class T> using *with-reference* = T&; *// exposition only* template<class T> concept *can-reference* *// exposition only* = requires { typename *with-reference*<T>; }; template<class T> concept *dereferenceable* *// exposition only* = requires(T& t) { { *t } -> *can-reference*; *// not required to be equality-preserving* }; <ins>template<class T> constexpr bool *is-integer-like* = *see below*; *// exposition only*</ins> […] *// 24.4.4 [[range.iter.ops]](https://wg21.link/range.iter.ops), range iterator operations* namespace ranges { *// 24.4.4.2 [[range.iter.op.advance]](https://wg21.link/range.iter.op.advance),* ranges::advance template<input_or_output_iterator I> constexpr void advance(I& i, iter_difference_t<I> n); *// freestanding* template<input_or_output_iterator I, <del>sentinel_for<I></del><ins>class</ins> S> <ins>requires (!*is-integer-like*<S>) && sentinel_for<S, I></ins> constexpr void advance(I& i, S bound); *// freestanding* template<input_or_output_iterator I, sentinel_for<I> S> constexpr iter_difference_t<I> advance(I& i, iter_difference_t<I> n, *// freestanding* S bound); […] *// 24.4.4.4 [[range.iter.op.next]](https://wg21.link/range.iter.op.next),* ranges::next template<input_or_output_iterator I> constexpr I next(I x); *// freestanding* template<input_or_output_iterator I> constexpr I next(I x, iter_difference_t<I> n); *// freestanding* template<input_or_output_iterator I, <del>sentinel_for<I></del><ins>class</ins> S> <ins>requires (!*is-integer-like*<S>) && sentinel_for<S, I></ins> constexpr I next(I x, S bound); *// freestanding* template<input_or_output_iterator I, sentinel_for<I> S> constexpr I next(I x, iter_difference_t<I> n, S bound); *// freestanding* } […] }
> 2. Modify 24.4.4.2 [[range.iter.op.advance]](https://wg21.link/range.iter.op.advance) as indicated: template<input_or_output_iterator I, <del>sentinel_for<I></del><ins>class</ins> S> <ins>requires (!*is-integer-like*<S>) && sentinel_for<S, I></ins> constexpr void advance(I& i, S bound); -3- *Preconditions*: […]
> 3. Modify 24.4.4.4 [[range.iter.op.next]](https://wg21.link/range.iter.op.next) as indicated: template<input_or_output_iterator I, <del>sentinel_for<I></del><ins>class</ins> S> <ins>requires (!*is-integer-like*<S>) && sentinel_for<S, I></ins> constexpr I next(I x, S bound); -3- *Effects*: […]

*[2026-02-20; Jonathan provides new wording]*

*[2026-02-27; LWG telecon: move to Ready]*

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify 24.3.4.7 [[iterator.concept.sentinel]](https://wg21.link/iterator.concept.sentinel) as indicated: template<class S, class I> concept sentinel_for = semiregular<S> && <ins>!*is-integer-like*<S> &&</ins> input_or_output_iterator<I> && weakly-equality-comparable-with<S, I>; *// see 18.5.4 [[concept.equalitycomparable]](https://wg21.link/concept.equalitycomparable)*

---

### Inconsistency between the deduction guide of std::mdspan taking (data_handle_type, mapping_type, accessor_type) 
and the corresponding constructor

**Section:** 23.7.3.6.1 [[mdspan.mdspan.overview]](https://wg21.link/mdspan.mdspan.overview) **Status:** [Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jiang An **Opened:** 2026-01-09 **Last modified:** 2026-02-20

**Priority:**Not Prioritized

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#mdspan.mdspan.overview) in [mdspan.mdspan.overview].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#mdspan.mdspan.overview) in [mdspan.mdspan.overview].

**Discussion:**

Currently, the following deduction guide of std::mdspan takes the data handle by reference:

> ```
> template<class MappingType, class AccessorType>
>   mdspan(const typename AccessorType::data_handle_type&, const MappingType&,
>          const AccessorType&)
>     -> mdspan<typename AccessorType::element_type, typename MappingType::extents_type,
>               typename MappingType::layout_type, AccessorType>;
> ```

But the corresponding constructor takes the data handle by value:

> ```
> constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a);
> ```

The distinction is observable with `volatile` glvalues. E.g., in the following example, CTAD fails but explicitly specifying template arguments works ([demo](https://godbolt.org/z/fPKb9869M)):

> ```
> #include <cstddef>
> #include <mdspan>
> 
> int main() {
>   int a[1]{};
>   int * volatile p = a;
>   std::mdspan(
>     p,
>     std::layout_right::mapping<std::extents<std::size_t, 1>>{},
>     std::default_accessor<int>{}); // error (but accidentally accepted by libc++)
>   std::mdspan<int, std::extents<std::size_t, 1>>(
>     p,
>     std::layout_left::mapping<std::extents<std::size_t, 1>>{},
>     std::default_accessor<int>{}); // OK
> }
> ```

Given we're generally passing data handle by value, it seems better to remove `const &` from `const typename AccessorType::data_handle_type&` in the deduction guide, which is more consistent with the constructor and accept more seemingly valid uses. Note that libc++ is accidentally doing this now by forgetting adding the `&`, see [llvm/llvm-project#175024](https://github.com/llvm/llvm-project/pull/175024).

*[2026-02-20; LWG telecon; Status changed: New → Ready.]*

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify 23.7.3.6.1 [[mdspan.mdspan.overview]](https://wg21.link/mdspan.mdspan.overview), class template `mdspan` synopsis, as indicated: namespace std { […] template<class MappingType, class AccessorType> mdspan(<del>const</del> typename AccessorType::data_handle_type<del>&</del>, const MappingType&, const AccessorType&) -> mdspan<typename AccessorType::element_type, typename MappingType::extents_type, typename MappingType::layout_type, AccessorType>; }

---

### The system_encoded_string() and generic_system_encoded_string() member functions 
of std::filesystem::path are misnamed

**Section:** 31.12.6.1 [[fs.class.path.general]](https://wg21.link/fs.class.path.general), 31.12.6.3.2 [[fs.path.type.cvt]](https://wg21.link/fs.path.type.cvt), 31.12.6.5.6 [[fs.path.native.obs]](https://wg21.link/fs.path.native.obs), 31.12.6.5.7 [[fs.path.generic.obs]](https://wg21.link/fs.path.generic.obs), D.22.2 [[depr.fs.path.obs]](https://wg21.link/depr.fs.path.obs) **Status:** [Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Tom Honermann **Opened:** 2026-01-11 **Last modified:** 2026-02-20

**Priority:**Not Prioritized

**Discussion:**

**Addresses [US 189-304](https://github.com/cplusplus/nbballot/issues/879)** The `system_encoded_string()` and `generic_system_encoded_string()` member functions of `std::filesystem::path` are misnamed. These functions were added as renamed versions of `string()` and `generic_string()` respectively by [P2319R5](https://wg21.link/P2319R5) ("Prevent path presentation problems"). The original function names are now deprecated. The C++ standard does not define "system encoding" and casual use of such a term is at best ambiguous. In common language, one might expect the "system encoding" to correspond to the environment encoding (for which `std::text_encoding::environment()` provides a definition) or the encoding of the current locale. However, neither of these encodings corresponds to the encoding these functions are expected to use. 31.12.6.3.2 [[fs.path.type.cvt]](https://wg21.link/fs.path.type.cvt) defines "native encoding" and, for `char`-based filesystem paths, states (in a note) that "For Windows-based operating systems, the native ordinary encoding is determined by calling a Windows API function." It is not specified which Windows API function is consulted, but existing implementations call `AreFileApisANSI()` to choose between the Active Code Page (`CP_ACP`) and the OEM Code Page (`CP_OEMCP`). Microsoft's implementation also checks for a thread-local locale and, if the locale encoding is UTF-8, prefers that (`CP_UTF8`) over either of the other two.

*[2026-02-20; LWG telecon; Status changed: New → Ready.]*

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify 31.12.6.1 [[fs.class.path.general]](https://wg21.link/fs.class.path.general), class `path` synopsis, as indicated: namespace std::filesystem { class path { public: […] // *31.12.6.5.6 [[fs.path.native.obs]](https://wg21.link/fs.path.native.obs), native format observers* […] std::string display_string() const; std::string <del>system</del><ins>native</ins>_encoded_string() const; std::wstring wstring() const; […] // *31.12.6.5.7 [[fs.path.generic.obs]](https://wg21.link/fs.path.generic.obs), generic format observers* […] std::string generic_display_string() const; std::string generic_<del>system</del><ins>native</ins>_encoded_string() const; std::wstring generic_wstring() const; […] }; }
2. Modify 31.12.6.3.2 [[fs.path.type.cvt]](https://wg21.link/fs.path.type.cvt) as indicated: -2- For member function arguments that take character sequences representing paths and for member functions returning strings, value type and encoding conversion is performed if the value type of the argument or return value differs from `path::value_type`. For the argument or return value, the method of conversion and the encoding to be converted to is determined by its value type: (2.1) — `char`: The encoding is the native ordinary encoding. The method of conversion, if any, is operating system dependent. [*Note 1*: For POSIX-based operating systems `path::value_type` is `char` so no conversion from `char` value type arguments or to `char` value type return values is performed. For Windows-based operating systems, the native ordinary encoding is determined by <del>calling a Windows API function</del><ins>the current locale encoding and the Windows `AreFileApisANSI` function</ins>. — end note] […] (2.2) — […] […]
3. Modify 31.12.6.5.6 [[fs.path.native.obs]](https://wg21.link/fs.path.native.obs) as indicated: std::string <del>system</del><ins>native</ins>_encoded_string() const; std::wstring wstring() const; std::u8string u8string() const; std::u16string u16string() const; std::u32string u32string() const; -7- *Returns*: `native()`. -8- *Remarks*: Conversion, if any, is performed as specified by 31.12.6.3 [[fs.path.cvt]](https://wg21.link/fs.path.cvt).
4. Modify 31.12.6.5.7 [[fs.path.generic.obs]](https://wg21.link/fs.path.generic.obs) as indicated: std::string generic_<del>system</del><ins>native</ins>_encoded_string() const; std::wstring generic_wstring() const; std::u8string generic_u8string() const; std::u16string generic_u16string() const; std::u32string generic_u32string() const; -5- *Returns*: The pathname in the generic format. -6- *Remarks*: Conversion, if any, is specified by 31.12.6.3 [[fs.path.cvt]](https://wg21.link/fs.path.cvt).
5. Modify D.22.2 [[depr.fs.path.obs]](https://wg21.link/depr.fs.path.obs) as indicated: std::string string() const; -2- *Returns*: `<del>system</del><ins>native</ins>_encoded_string()`. std::string generic_string() const; -3- *Returns*: `generic_<del>system</del><ins>native</ins>_encoded_string()`.

---

### Disallow user specialization of <simd> templates

**Section:** 29.10.1 [[simd.general]](https://wg21.link/simd.general) **Status:** [Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Tim Song **Opened:** 2026-03-05 **Last modified:** 2026-03-06

**Priority:**Not Prioritized

**Discussion:**


Addresses [US 176-280](https://github.com/cplusplus/nbballot/issues/855).


It does not appear that any of the class templates in `<simd>` can be profitably specialized by the user – or that the non-member functions can be used with such user specializations.

*[2026-03-06 LWG telecon; move to Ready]*

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Add the following paragraph to the end of 29.10.1 [[simd.general]](https://wg21.link/simd.general): <ins>-?- If a program declares an explicit or partial specialization of any of the templates specified in subclause 29.10 [[simd]](https://wg21.link/simd), the program is ill-formed, no diagnostic required.</ins>
2. Strike 29.10.4 [[simd.traits]](https://wg21.link/simd.traits) p3 as redundant: <del>-3- The behavior of a program that adds specializations for `alignment` is undefined.</del>

---

### Type traits have inconsistent interactions with immediate functions

**Section:** 21.3.6.4 [[meta.unary.prop]](https://wg21.link/meta.unary.prop), 21.3.8 [[meta.rel]](https://wg21.link/meta.rel) **Status:** [Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Tim Song **Opened:** 2026-03-05 **Last modified:** 2026-03-06

**Priority:**Not Prioritized

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#meta.unary.prop) in [meta.unary.prop].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#meta.unary.prop) in [meta.unary.prop].

**Discussion:**

Per 7.7 [[expr.const]](https://wg21.link/expr.const)p23, calls to immediate functions are not immediate invocations, and therefore are not required to result in constant expressions, if the call occurs in an unevaluated operand. Currently, some type traits (e.g. `is_assignable`, `is_invocable`) specify that the construct at issue is treated as an unevaluated operand, while others (`is_constructible`, `is_convertible`) do not. This seems like a bad state of affairs. The wording below makes everything unevaluated (and hence not check for constant-ness) to match the behavior of `requires` expressions (and implementations). This arguably makes the traits less useful in some contexts where false negatives are tolerable but false positives are not.

*[2026-03-06 LWG telecon; move to Ready]*

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify [tab:meta.unary.prop], Table 54 — Type property predicates as indicated: TemplateConditionPreconditions ……… `template<class T, class U> struct reference_constructs_from_temporary;` `T` is a reference type, and the initialization `T t(*VAL*<U>);` is well-formed and binds `t` to a temporary object whose lifetime is extended (6.8.7 [[class.temporary]](https://wg21.link/class.temporary)). <ins>The full-expression of the variable initialization is treated as an unevaluated operand (7.2.3 [[expr.context]](https://wg21.link/expr.context)).</ins> Access checking is performed as if in a context unrelated to `T` and `U`. Only the validity of the immediate context of the variable initialization is considered. [*Note 5:* … — *end note*] […] `template<class T, class U> struct reference_converts_from_temporary;` `T` is a reference type, and the initialization `T t = *VAL*<U>;` is well-formed and binds `t` to a temporary object whose lifetime is extended (6.8.7 [[class.temporary]](https://wg21.link/class.temporary)). <ins>The full-expression of the variable initialization is treated as an unevaluated operand (7.2.3 [[expr.context]](https://wg21.link/expr.context)).</ins> Access checking is performed as if in a context unrelated to `T` and `U`. Only the validity of the immediate context of the variable initialization is considered. [*Note 6:* … — *end note*] […] ………
2. Modify 21.3.6.4 [[meta.unary.prop]](https://wg21.link/meta.unary.prop) p9 as indicated: -9- The predicate condition for a template specialization `is_constructible<T, Args...>` shall be satisfied if and only if the following variable definition would be well-formed for some invented variable `t`: T t(declval<Args>()...); [*Note 7:* … — *end note*] <ins>The full-expression of the variable initialization is treated as an unevaluated operand (7.2.3 [[expr.context]](https://wg21.link/expr.context)).</ins> Access checking is performed as if in a context unrelated to `T` and any of the `Args`. Only the validity of the immediate context of the variable initialization is considered. [*Note 8:* … — *end note*]
3. Modify 21.3.8 [[meta.rel]](https://wg21.link/meta.rel) p6 as indicated: -9- The predicate condition for a template specialization `is_convertible<From, To>` shall be satisfied if and only if the return <del>expression</del><ins>statement (8.8.4 [[stmt.return]](https://wg21.link/stmt.return))</ins> in the following code would be well-formed, including any implicit conversions to the return type of the function: To test() { return declval<From>(); } [*Note 4:* … — *end note*] Access checking is performed in a context unrelated to `To` and `From`. <ins>The operand of the `return` statement (including initialization of the returned object or reference, if any) is treated as an unevaluated operand (7.2.3 [[expr.context]](https://wg21.link/expr.context)), and only the validity of its immediate context is considered.</ins> <del>Only the validity of the immediate context of the *expression* of the `return` statement (8.8.4 [[stmt.return]](https://wg21.link/stmt.return)) (including initialization of the returned object or reference) is considered.</del> [*Note 5:* … — *end note*]

## Tentatively Ready Issues

---

### Two-digit formatting of negative year is ambiguous

**Section:** 30.12 [[time.format]](https://wg21.link/time.format), 30.13 [[time.parse]](https://wg21.link/time.parse) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Matt Stephanson **Opened:** 2022-11-18 **Last modified:** 2025-12-04

**Priority:**3

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#time.format) in [time.format].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#time.format) in [time.format].

**Discussion:**

An [issue](https://github.com/microsoft/STL/issues/3166) has been identified regarding the two-digit formatting of negative years according to Table [tab:time.format.spec] (30.12 [[time.format]](https://wg21.link/time.format)):

> ```
> cout << format("{:%y} ", 1976y)  // "76"
>      << format("{:%y}", -1976y); // also "76"?
> ```

The relevant wording is

> The last two decimal digits of the year. If the result is a single digit it is prefixed by `0`. The modified command `%Oy` produces the locale's alternative representation. The modified command `%Ey` produces the locale's alternative representation of offset from `%EC` (year only).

MSVC STL treats the regular modified form symmetrically. Just as `%Ey` is the offset from `%EC`, so `%y` is the offset from `%C`, which is itself "[t]he year divided by 100 using *floored division*." (emphasis added). Because -1976 is the 24th year of the -20th century, the above code will print "76 24" using MSVC STL. However, many users expect, and [libc++](https://github.com/llvm/llvm-project/blob/8f3f15c1a208932689a8bdef22d6ca3d4c3408c5/libcxx/include/__chrono/formatter.h#L238-L240) gives, a result based on the literal wording, "76 76". [IEEE 1003.1-2008 strftime](https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/functions/strftime.html) expects the century to be nonnegative, but the glibc implementation [prints 24](https://godbolt.org/z/1jYoeYT9d) for -1976. My own opinion is that this is the better result, because it consistently interprets `%C` and `%y` as the quotient and remainder of floored division by 100. Howard Hinnant, coauthor of the original 30.12 [[time.format]](https://wg21.link/time.format) wording in [P0355](https://wg21.link/P0355) adds:

> On the motivation for this design it is important to remember a few things:
> 
> - POSIX `strftime`/`strptime` doesn't handle negative years in this department, so this is an opportunity for an extension in functionality.
> - This is a formatting/parsing issue, as opposed to a computational issue. This means that human readability of the string syntax is the most important aspect. Computational simplicity takes a back seat (within reason).
> - `%C` can't be truncated division, otherwise the years [-99, -1] would map to the same century as the years [0, 99]. So floored division is a pretty easy and obvious solution.
> - `%y` is obvious for non-negative years: The last two decimal digits, or `y % 100`.
> 
> This leaves how to represent negative years with `%y`. I can think of 3 options:
> 
> 1. Use the last two digits without negating: -1976 → 76.
> 2. Use the last two digits and negate it: -1976 → -76.
> 3. Use floored modulus arithmetic: -1976 → 24.
> 
> The algorithm to convert `%C` and `%y` into a year is not important to the client because these are both strings, not integers. The client will do it with `parse`, not `100*C + y`. I discounted solution 3 as not sufficiently obvious. If the output for -1976 was 23, the human reader wouldn't immediately know that this is off by 1. The reader is expecting the POSIX spec:
> 
> > the last two digits of the year as a decimal number [00,99].
> 
> 24 just doesn't cut it. That leaves solution 1 or 2. I discounted solution 2 because having the negative in 2 places (the `%C` and `%y`) seemed overly complicated and more error prone. The negative sign need only be in one place, and it has to be in `%C` to prevent ambiguity. That leaves solution 1. I believe this is the solution for an extension of the POSIX spec to negative years with the property of least surprise to the client. The only surprise is in `%C`, not `%y`, and the surprise in `%C` seems unavoidable.

*[2022-11-30; Reflector poll]*

Set priority to 3 after reflector poll.

A few votes for priority 2. Might need to go to LEWG.

**Previous resolution [SUPERSEDED]:**

> This wording is relative to [N4917](https://wg21.link/N4917).
> 
> > [*Drafting Note:* Two mutually exclusive options are prepared, depicted below by **Option A** and **Option B**, respectively.]
> 
> **Option A:** This is Howard Hinnant's choice (3)
> 
> 1. Modify 30.12 [[time.format]](https://wg21.link/time.format), Table [tab:time.format.spec] as indicated: Table 102 — Meaning of conversion specifiers [tab:time.format.spec] Specifier Replacement `[…]` `%y` The <del>last two decimal digits of the year</del><ins>remainder after dividing the year by 100 using floored division</ins>. If the result is a single digit it is prefixed by `0`. The modified command `%Oy` produces the locale's alternative representation. The modified command `%Ey` produces the locale's alternative representation of offset from `%EC` (year only). `[…]`
> 2. Modify 30.13 [[time.parse]](https://wg21.link/time.parse), Table [tab:time.parse.spec] as indicated: Table 103 — Meaning of `parse` flags [tab:time.parse.spec] Flag Parsed value `[…]` `%y` The <del>last two decimal digits of the year</del><ins>remainder after dividing the year by 100 using floored division</ins>. If the century is not otherwise specified (e.g. with `%C`), values in the range [`69`, `99`] are presumed to refer to the years 1969 to 1999, and values in the range [`00`, `68`] are presumed to refer to the years 2000 to 2068. The modified command `%*N* y` specifies the maximum number of characters to read. If *N* is not specified, the default is 2. Leading zeroes are permitted but not required. The modified commands `%Ey` and `%Oy` interpret the locale's alternative representation. `[…]`
> 
> **Option B:** This is Howard Hinnant's choice (1)
> 
> 1. Modify 30.12 [[time.format]](https://wg21.link/time.format), Table [tab:time.format.spec] as indicated: Table 102 — Meaning of conversion specifiers [tab:time.format.spec] Specifier Replacement `[…]` `%y` The last two decimal digits of the year<ins>, regardless of the sign of the year</ins>. If the result is a single digit it is prefixed by `0`. The modified command `%Oy` produces the locale's alternative representation. The modified command `%Ey` produces the locale's alternative representation of offset from `%EC` (year only). <ins>[*Example ?:* `cout << format("{:%C %y}", -1976y);` prints `-20 76`. — *end example*]</ins> `[…]`
> 2. Modify 30.13 [[time.parse]](https://wg21.link/time.parse), Table [tab:time.parse.spec] as indicated: Table 103 — Meaning of `parse` flags [tab:time.parse.spec] Flag Parsed value `[…]` `%y` The last two decimal digits of the year<ins>, regardless of the sign of the year</ins>. If the century is not otherwise specified (e.g. with `%C`), values in the range [`69`, `99`] are presumed to refer to the years 1969 to 1999, and values in the range [`00`, `68`] are presumed to refer to the years 2000 to 2068. The modified command `%*N* y` specifies the maximum number of characters to read. If *N* is not specified, the default is 2. Leading zeroes are permitted but not required. The modified commands `%Ey` and `%Oy` interpret the locale's alternative representation. <ins>[*Example ?:* `year y; istringstream{"-20 76"} >> parse("%3C %y", y);` results in `y == -1976y`. — *end example*]</ins> `[…]`

*[2025-10-17; Jonathan provides updated wording using Option B]*

*[2025-12-04; Reflector poll.]*

Set status to Tentatively Ready after seven votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5014](https://wg21.link/N5014).

1. Modify 30.12 [[time.format]](https://wg21.link/time.format), Table [tab:time.format.spec] as indicated: Table 133 — Meaning of conversion specifiers [tab:time.format.spec] Specifier Replacement `[…]` `%y` The last two decimal digits of the year<ins>, regardless of the sign of the year</ins>. If the result is a single digit it is prefixed by `0`. The modified command `%Oy` produces the locale's alternative representation. The modified command `%Ey` produces the locale's alternative representation of offset from `%EC` (year only). <ins>[*Example ?:* `cout << format("{:%C %y}", -1976y);` prints `-20 76`. — *end example*]</ins> `[…]`
2. Modify 30.13 [[time.parse]](https://wg21.link/time.parse), Table [tab:time.parse.spec] as indicated: Table 103 — Meaning of `parse` flags [tab:time.parse.spec] Flag Parsed value `[…]` `%y` The last two decimal digits of the year<ins>, regardless of the sign of the year</ins>. If the century is not otherwise specified (e.g. with `%C`), values in the range [`69`, `99`] are presumed to refer to the years 1969 to 1999, and values in the range [`00`, `68`] are presumed to refer to the years 2000 to 2068. The modified command `%*N* y` specifies the maximum number of characters to read. If *N* is not specified, the default is 2. Leading zeroes are permitted but not required. The modified commands `%Ey` and `%Oy` interpret the locale's alternative representation. <ins>[*Example ?:* `year y; istringstream{"-20 76"} >> parse("%3C %y", y);` results in `y == -1976y`. — *end example*]</ins> `[…]`

---

### Underspecified use of locale facets for locale-dependent std::format

**Section:** 28.5.2.2 [[format.string.std]](https://wg21.link/format.string.std) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jens Maurer **Opened:** 2024-04-30 **Last modified:** 2026-01-19

**Priority:**3

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#format.string.std) in [format.string.std].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#format.string.std) in [format.string.std].

**Discussion:**

There are `std::format` variants that take an explicit `std::locale` parameter. There is the `"L"` format specifier that uses that locale (or some environment locale) for formatting, according to 28.5.2.2 [[format.string.std]](https://wg21.link/format.string.std) p17:

> "For integral types, the locale-specific form causes the context's locale to be used to insert the appropriate digit group separator characters."

It is unclear which specific facets are used to make this happen. This is important, because users can install their own facets into a given locale. Specific questions include:

- Is `num_put<>` being used? Or just `numpunct<>`?
- Are any of the `_byname` facets being used?

Assuming the encoding for `char` is UTF-8, the use of a user-provided `num_put<>` facet (as opposed to `std::format` creating the output based on `numpunct<>`) would allow digit separators that are not expressibly as a single UTF-8 code unit.

*[2024-05-08; Reflector poll]*

Set priority to 3 after reflector poll.

*[2024-06-12; SG16 meeting]*

The three major implementations all use `numpunct` but not `num_put`, clarify that this is the intended behaviour.

*[2025-06-12; Jonathan provides wording]*

**Previous resolution [SUPERSEDED]:**

> This wording is relative to [N5008](https://wg21.link/N5008).
> 
> 1. Modify 28.5.2.2 [[format.string.std]](https://wg21.link/format.string.std) as indicated: -17- When the `L` option is used, the form used for the conversion is called the *locale-specific* form. The `L` option is only valid for arithmetic types, and its effect depends upon the type. (17.1) — For integral types, the locale-specific form causes the context’s locale to be used to insert the appropriate digit group separator characters <ins> as if obtained with `numpunct<ins><charT></ins>::grouping` and `numpunct<ins><charT></ins>::thousands_sep` </ins>. (17.2) — For floating-point types, the locale-specific form causes the context’s locale to be used to insert the appropriate digit group and radix separator characters <ins> as if obtained with `numpunct<ins><charT></ins>::grouping`, `numpunct<ins><charT></ins>::thousands_sep`, and `numpunct<ins><charT></ins>::decimal_point` </ins>. (17.3) — For the textual representation of `bool`, the locale-specific form causes the context’s locale to be used to insert the appropriate string as if obtained with `numpunct<ins><charT></ins>::truename` or `numpunct<ins><charT></ins>::falsename`.

*[2025-08-27; SG16 meeting]*

SG16 unanimously approved new wording from Victor. The new wording incorporates similar wording as added by [P2419R2](https://wg21.link/P2419R2) to address [3565](https://cplusplus.github.io/LWG/lwg-defects.html#3565)<sup>[(i)](https://cplusplus.github.io/LWG/issue3565)</sup>. Status updated SG16 → Open.

*[2026-01-16; Reflector poll.]*

Set status to Tentatively Ready after six votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5014](https://wg21.link/N5014).

1. Modify 28.5.2.2 [[format.string.std]](https://wg21.link/format.string.std) as indicated: -17- When the `L` option is used, the form used for the conversion is called the *locale-specific* form. The `L` option is only valid for arithmetic types, and its effect depends upon the type. (17.1) — For integral types, the locale-specific form causes the context’s locale to be used to insert the appropriate digit group separator characters <ins> as if obtained with `numpunct<ins><charT></ins>::grouping` and `numpunct<ins><charT></ins>::thousands_sep` </ins>. (17.2) — For floating-point types, the locale-specific form causes the context’s locale to be used to insert the appropriate digit group and radix separator characters <ins> as if obtained with `numpunct<ins><charT></ins>::grouping`, `numpunct<ins><charT></ins>::thousands_sep`, and `numpunct<ins><charT></ins>::decimal_point` </ins>. (17.3) — For the textual representation of `bool`, the locale-specific form causes the context’s locale to be used to insert the appropriate string as if obtained with `numpunct<ins><charT></ins>::truename` or `numpunct<ins><charT></ins>::falsename`. <ins> If the string literal encoding is a Unicode encoding form and the locale is among an implementation-defined set of locales, each replacement that depends on the locale is performed as if the replacement character sequence is converted to the string literal encoding. </ins>

---

### Preconditions for std::launder might be overly strict

**Section:** 17.6.5 [[ptr.launder]](https://wg21.link/ptr.launder) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jiang An **Opened:** 2024-07-30 **Last modified:** 2026-02-13

**Priority:**3

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#ptr.launder) in [ptr.launder].

**Discussion:**

From issue [cplusplus/draft#4553](https://github.com/cplusplus/draft/issues/4553) which is considered non-editorial. Currently, `std::launder` has a precondition that the pointed to object must be within its lifetime. However, per the example added by [P0593R6](https://wg21.link/P0593R6), it's probably intended that the result of `std::launder` should be allowed to point to an array element subobject whose lifetime has not started yet.

*[2024-10-02; Reflector poll]*

Set priority to 3 after reflector poll. Needs review by Core.

*[Wrocław 2024-11-18; approved by Core]*

*[2026-02-13; Reflector poll.]*

Set status to Tentatively Ready after seven votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N4986](https://wg21.link/N4986).

1. Modify 17.6.5 [[ptr.launder]](https://wg21.link/ptr.launder) as indicated: template<class T> [[nodiscard]] constexpr T* launder(T* p) noexcept; -1- *Mandates*: `!is_function_v<T> && !is_void_v<T>` is `true`. -2- *Preconditions*: `p` represents the address *A* of a byte in memory. An object *X* <del>that is within its lifetime (6.8.4 [[basic.life]](https://wg21.link/basic.life)) and</del> whose type is similar (7.3.6 [[conv.qual]](https://wg21.link/conv.qual)) to `T` is located at the address *A*<ins>, and is either within its lifetime (6.8.4 [[basic.life]](https://wg21.link/basic.life)) or is an array element subobject whose containing array object is within its lifetime</ins>. All bytes of storage that would be reachable through (6.9.4 [[basic.compound]](https://wg21.link/basic.compound)) the result are reachable through `p`. -3- *Returns*: A value of type `T*` that points to *X*. […]

---

### P1148R0 changed the return values of searching functions of std::basic_string on some platforms

**Section:** 27.4.3.8.2 [[string.find]](https://wg21.link/string.find) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jiang An **Opened:** 2025-05-05 **Last modified:** 2025-12-04

**Priority:**3

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#string.find) in [string.find].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#string.find) in [string.find].

**Discussion:**

[P1148R0](https://wg21.link/P1148R0) respecified the searching functions of `std::basic_string` to return corresponding string view type's `npos` member constant (equal to `std::size_t(-1)`), converted to the string type `S`'s member `S::size_type`, when the search fails. Before the change, `S::npos` (equal to `S::size_type(-1)`) was returned on failure. On platforms where `std::size_t` isn't the widest unsigned integer type (e.g. on usual 32-bit platforms), the return value can change. Because there can be an allocator with a wider size_type, and when the basic_string type `S` uses such an allocator, `S::size_type` is specified to be that type, which in turn makes `S::size_type(std::size_t(-1))` not equal to `S::size_type(-1)`. Do we want to restore the old return values?

**Previous resolution [SUPERSEDED]:**

> This wording is relative to [N5008](https://wg21.link/N5008).
> 
> 1. Modify 27.4.3.8.2 [[string.find]](https://wg21.link/string.find) as indicated: template<class T> constexpr size_type find(const T& t, size_type pos = 0) const noexcept(*see below*); […] template<class T> constexpr size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept(*see below*); -2- *Constraints*: […] -3- *Effects*: Let `*G*` be the name of the function. Equivalent to: basic_string_view<charT, traits> s = *this, sv = t; <del>return s.*G*(sv, pos);</del> <ins>if (auto result = s.*G*(sv, pos); result == size_t(-1)) return npos; else return result;</ins>

*[2025-06-10, reflector discussion]*

During reflector discussion of this issue there was a preference to adjust the proposed wording to use `s.npos` instead of `size_t(-1)`.

*[2025-10-21; Reflector poll.]*

Set priority to 3 after reflector poll.

*[2025-12-04; Reflector poll.]*

Set status to Tentatively Ready after five votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5008](https://wg21.link/N5008).

1. Modify 27.4.3.8.2 [[string.find]](https://wg21.link/string.find) as indicated: template<class T> constexpr size_type find(const T& t, size_type pos = 0) const noexcept(*see below*); […] template<class T> constexpr size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept(*see below*); -2- *Constraints*: […] -3- *Effects*: Let `*G*` be the name of the function. Equivalent to: basic_string_view<charT, traits> s = *this, sv = t; <del>return s.*G*(sv, pos);</del> <ins>if (auto result = s.*G*(sv, pos); result == s.npos) return npos; else return result;</ins>

---

### unique_ptr<void>::operator* is not SFINAE-friendly

**Section:** 20.3.1.3.5 [[unique.ptr.single.observers]](https://wg21.link/unique.ptr.single.observers) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Hewill Kang **Opened:** 2025-08-24 **Last modified:** 2025-12-04

**Priority:**3

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#unique.ptr.single.observers) in [unique.ptr.single.observers].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#unique.ptr.single.observers) in [unique.ptr.single.observers].

**Discussion:**

LWG [2762](https://cplusplus.github.io/LWG/lwg-defects.html#2762)<sup>[(i)](https://cplusplus.github.io/LWG/issue2762)</sup> added a conditional `noexcept` specification to `unique_ptr::operator*` to make it consistent with `shared_ptr::operator*`:

```
constexpr add_lvalue_reference_t<T> operator*() const noexcept(noexcept(*declval<pointer>()));
```

This unexpectedly makes `unique_ptr<void>::operator*` no longer SFINAE-friendly, [for example](https://godbolt.org/z/xd15jYPhz):

> ```
> #include <memory>
> 
> template<class T> concept dereferenceable = requires(T& t) { *t; };
> 
> static_assert( dereferenceable<int *>);
> static_assert(!dereferenceable<void*>);
> 
> static_assert( dereferenceable<std::shared_ptr<int >>);
> static_assert(!dereferenceable<std::shared_ptr<void>>);
> 
> static_assert( dereferenceable<std::unique_ptr<int >>);
> static_assert( dereferenceable<std::unique_ptr<void>>); // hard error
> ```

Given that the standard intends for `operator*` of `shared_ptr` and `unique_ptr` to be SFINAE-friendly based on 20.3.2.2.6 [[util.smartptr.shared.obs]](https://wg21.link/util.smartptr.shared.obs), regardless of the value of `static_assert`, it is reasonable to assume that there should be no hard error here.

**Previous resolution [SUPERSEDED]:**

> This wording is relative to [N5014](https://wg21.link/N5014).
> 
> 1. Modify 20.3.1.3.5 [[unique.ptr.single.observers]](https://wg21.link/unique.ptr.single.observers) as indicated: constexpr add_lvalue_reference_t<T> operator*() const noexcept(<del>noexcept(*declval<pointer>())</del><ins>*see below*</ins>); -1- *Mandates*: `reference_converts_from_temporary_v<add_lvalue_reference_t<T>, decltype(*declval<pointer>())>` is `false`. -2- *Preconditions*: `get() != nullptr` is `true`. -3- *Returns*: `*get()`. <ins>-?- *Remarks:*: The exception specification is equivalent to:</ins> <ins>!requires { *declval<pointer>(); } || requires { { *declval<pointer>() } noexcept; }</ins>

*[2025-08-26; Reflector discussion]*

During reflector triaging it had been pointed out that a better solution would be to constrain the `operator*` directly. The proposed wording has been updated to that effect.

*[2025-10-22; Reflector poll.]*

Set priority to 3 after reflector poll.

*[2025-12-04; Reflector poll.]*

Set status to Tentatively Ready after eight votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5014](https://wg21.link/N5014).

1. Modify 20.3.1.3.5 [[unique.ptr.single.observers]](https://wg21.link/unique.ptr.single.observers) as indicated: constexpr add_lvalue_reference_t<T> operator*() const noexcept(noexcept(*declval<pointer>())); <ins>-?- *Constraints*: `*declval<pointer>()` is a well-formed expression.</ins> -1- *Mandates*: `reference_converts_from_temporary_v<add_lvalue_reference_t<T>, decltype(*declval<pointer>())>` is `false`. -2- *Preconditions*: `get() != nullptr` is `true`. -3- *Returns*: `*get()`.

---

### Inconsistency between std::basic_string's data() and operator[] specification

**Section:** 27.4.3.6 [[string.access]](https://wg21.link/string.access) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Peter Bindels **Opened:** 2025-09-16 **Last modified:** 2026-03-06

**Priority:**4

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#string.access) in [string.access].

**Discussion:**

From the working draft [N5014](https://wg21.link/N5014), the specification for `operator[]` in 27.4.3.6 [[string.access]](https://wg21.link/string.access) p2 says:

> *Returns*: `*(begin() + pos)` if `pos < size()`. Otherwise, returns a reference to an object of type `charT` with value `charT()`, where modifying the object to any value other than `charT()` leads to undefined behavior.

The specification for data() in 27.4.3.8.1 [[string.accessors]](https://wg21.link/string.accessors) p1 (and p4) says, however:

> *Returns*: A pointer `p` such that `p + i == addressof(operator[](i))` for each `i` in `[0, size()]`.

The former implies that `str[str.size()]` is allowed to be the address of any null terminator, while the latter restricts it to only being the null terminator belonging to the string. Suggested fix: Change wording around `operator[]` to

> *Returns*: `*(begin() + pos)` if `pos <= size()`. The program shall not modify the value stored at `size()` to any value other than `charT()`; otherwise, the behavior is undefined.

This moves it inline with the `data()` specification. Given the hardened precondition that `pos <= size()` this does not change behavior for any in-contract access, and we do not define what the feature does when called with broken preconditions. I have been looking at the latter but that will be an EWG paper instead.

*[2025-10-21; Reflector poll.]*

Set priority to 4 after reflector poll.

"NAD. `begin() + size()` is not dereferenceable and should remain that way."

"Saying "if `pos <= size()` is redundant given the precondition above."

"The resolution removes any guarantee that the value at `str[str.size()]` is `charT()`. Furthermore, the premise of the issue is incorrect, returning the address of a different null terminator not belonging to the string would make traversing it with other string operations UB, so it has to return a reference to a terminator that's within the same array."

"`*(begin() = size())` is UB, but could use `*(data() + size())` instead. Personally I'd like `*end()` to be valid, but that's certainly LEWG business requiring a paper."

**Previous resolution [SUPERSEDED]:**

> This wording is relative to [N5014](https://wg21.link/N5014).
> 
> 1. Modify 27.4.3.6 [[string.access]](https://wg21.link/string.access) as indicated: constexpr const_reference operator[](size_type pos) const; constexpr reference operator[](size_type pos); -1- *Hardened preconditions*: `pos <= size()` is `true`. -2- *Returns*: `*(begin() + pos)` if `pos <<ins>=</ins> size()`. <del>Otherwise, returns a reference to an object of type `charT` with value `charT()`, where modifying the object to any value other than `charT()` leads to undefined behavior.</del> -3- *Throws*: Nothing. -4- *Complexity*: Constant time. <ins>-?- *Remarks* The program shall not modify the value stored at `size()` to any value other than `charT()`; otherwise, the behavior is undefined</ins>

*[2025-11-11; Jonathan provides new wording]*

We say that `basic_string` is a contiguous container, which makes the `addressof` wording in `c_str()` and `data()` redundant. The front matter says that there's a null terminator present, so we can move the rule about not modifying the terminator there instead of repeating it in `operator[]` and `c_str()`.

We can also permit modifying the string contents through `const_cast<char*>(str.c_str())[0]`. There's no reason for that to be undefined when `const_cast<string&>(str)[0]` and `const_cast<string&>(str).data()[0]` are both allowed. The only restriction should be on changing the null terminator. Changing any other characters through `c_str() const` or `data() const` is no different to changing them through the non-const `data()`, and does not need to cause undefined behaviour.

**Previous resolution [SUPERSEDED]:**

> This wording is relative to [N5014](https://wg21.link/N5014).
> 
> 1. Modify 27.4.3.1 [[basic.string.general]](https://wg21.link/basic.string.general) as indicated: -3- In all cases, [`data()`, `data() + size()`] is a valid range, `data() + size()` points at an object with value `charT()` (a "null terminator"), and `size() <= capacity()` is `true`. <ins> Non-const access to the null terminator is possible, e.g. using `*(data()+size())`, but the program has undefined behavior if the null terminator is modified to any value other than `charT()`. </ins>
> 2. Modify 27.4.3.6 [[string.access]](https://wg21.link/string.access) as indicated: constexpr const_reference operator[](size_type pos) const; constexpr reference operator[](size_type pos); -1- *Hardened Preconditions*: `pos <= size()` is `true`. -2- *Returns*: <ins>`*(data() + pos)`.</ins> <del> `*(begin() + pos)` if `pos < size()`. Otherwise, returns a reference to an object of type `charT` with value `charT()`, where modifying the object to any value other than `charT()` leads to undefined behavior. </del> -3- *Throws*: Nothing. -4- *Complexity*: Constant time.
> 3. Modify 27.4.3.8.1 [[string.accessors]](https://wg21.link/string.accessors) as indicated: constexpr const charT* c_str() const noexcept; constexpr const charT* data() const noexcept; <ins>constexpr charT* data() noexcept;</ins> -1- *Returns*: <ins>`to_address(begin())`.</ins> <del> A pointer `p` such that `p + i == addressof(operator[](i))` for each `i` in [`0`, `size()`]. </del> -2- *Complexity*: Constant time. <del>-3- *Remarks*: The program shall not modify any of the values stored in the character array; otherwise, the behavior is undefined.</del> <del>constexpr charT* data() noexcept;</del> <del>-4- *Returns*: A pointer `p` such that `p + i == addressof(operator[](i))` for each `i` in [`0`, `size()`]. </del> <del>-5- *Complexity*: Constant time.</del> <del>-6- *Remarks*: The program shall not modify the value stored at `p + size()` to any value other than `charT()`; otherwise, the behavior is undefined.</del>

*[2026-02-27; Jonathan provides new wording]*

*[2026-03-06; Reflector poll.]*

Set status to Tentatively Ready after nine votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify 27.4.3.1 [[basic.string.general]](https://wg21.link/basic.string.general) as indicated: -3- In all cases, [`data()`, `data() + size()`] is a valid range, `data() + size()` points at an object with value `charT()` (a "null terminator"), and `size() <= capacity()` is `true`. <ins> The program has undefined behavior if the null terminator is modified to any value other than `charT()`. </ins>
2. Modify 27.4.3.6 [[string.access]](https://wg21.link/string.access) as indicated: constexpr const_reference operator[](size_type pos) const; constexpr reference operator[](size_type pos); -1- *Hardened Preconditions*: `pos <= size()` is `true`. -2- *Returns*: <ins>`data()[pos]`.</ins> <del> `*(begin() + pos)` if `pos < size()`. Otherwise, returns a reference to an object of type `charT` with value `charT()`, where modifying the object to any value other than `charT()` leads to undefined behavior. </del> -3- *Throws*: Nothing. -4- *Complexity*: Constant time.
3. Modify 27.4.3.8.1 [[string.accessors]](https://wg21.link/string.accessors) as indicated: constexpr const charT* c_str() const noexcept; constexpr const charT* data() const noexcept; <ins>constexpr charT* data() noexcept;</ins> -1- *Returns*: <ins>`to_address(begin())`.</ins> <del> A pointer `p` such that `p + i == addressof(operator[](i))` for each `i` in [`0`, `size()`]. </del> -2- *Complexity*: Constant time. <del>-3- *Remarks*: The program shall not modify any of the values stored in the character array; otherwise, the behavior is undefined.</del> <del>constexpr charT* data() noexcept;</del> <del>-4- *Returns*: A pointer `p` such that `p + i == addressof(operator[](i))` for each `i` in [`0`, `size()`]. </del> <del>-5- *Complexity*: Constant time.</del> <del>-6- *Remarks*: The program shall not modify the value stored at `p + size()` to any value other than `charT()`; otherwise, the behavior is undefined.</del>

---

### freestanding for stable_sort, stable_partition and inplace_merge

**Section:** 26.4 [[algorithm.syn]](https://wg21.link/algorithm.syn) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Braden Ganetsky **Opened:** 2025-11-06 **Last modified:** 2026-01-16

**Priority:**Not Prioritized

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#algorithm.syn) in [algorithm.syn].

**Discussion:**

Addresses [US 157-255](https://github.com/cplusplus/nbballot/issues/830)

This applies the resolution for US 157-255.

*[2026-01-16; Reflector poll.]*

Set status to Tentatively Ready after ten votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5014](https://wg21.link/N5014).

1. Modify 26.4 [[algorithm.syn]](https://wg21.link/algorithm.syn), as indicated: namespace ranges { template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I stable_sort(I first, S last, Comp comp = {}, Proj proj = {}); // hosted template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> stable_sort(R&& r, Comp comp = {}, Proj proj = {}); // hosted template<execution-policy Ep, random_access_iterator I, sized_sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> I stable_sort(Ep&& exec, I first, S last, Comp comp = {}, Proj proj = {}); // <del>freestanding-deleted</del><ins>hosted</ins> template<execution-policy Ep, sized-random-access-range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> borrowed_iterator_t<R> stable_sort(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); // <del>freestanding-deleted</del><ins>hosted</ins> }
2. Modify 26.4 [[algorithm.syn]](https://wg21.link/algorithm.syn), as indicated: namespace ranges { template<bidirectional_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> requires permutable<I> constexpr subrange<I> stable_partition(I first, S last, Pred pred, // hosted Proj proj = {}); template<bidirectional_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires permutable<iterator_t<R>> constexpr borrowed_subrange_t<R> stable_partition(R&& r, Pred pred, // hosted Proj proj = {}); template<execution-policy Ep, random_access_iterator I, sized_sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> requires permutable<I> subrange<I> stable_partition(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); // <del>freestanding-deleted</del><ins>hosted</ins> template<execution-policy Ep, sized-random-access-range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires permutable<iterator_t<R>> borrowed_subrange_t<R> stable_partition(Ep&& exec, R&& r, Pred pred, Proj proj = {}); // <del>freestanding-deleted</del><ins>hosted</ins> }
3. Modify 26.4 [[algorithm.syn]](https://wg21.link/algorithm.syn), as indicated: namespace ranges { template<bidirectional_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); // hosted template<bidirectional_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> inplace_merge(R&& r, iterator_t<R> middle, Comp comp = {}, Proj proj = {}); // hosted template<execution-policy Ep, random_access_iterator I, sized_sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> I inplace_merge(Ep&& exec, I first, I middle, S last, Comp comp = {}, Proj proj = {}); // <del>freestanding-deleted</del><ins>hosted</ins> template<execution-policy Ep, sized-random-access-range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> borrowed_iterator_t<R> inplace_merge(Ep&& exec, R&& r, iterator_t<R> middle, Comp comp = {}, Proj proj = {}); // <del>freestanding-deleted</del><ins>hosted</ins> }

---

### Missing Throws: for last variant constructor

**Section:** 22.6.3.2 [[variant.ctor]](https://wg21.link/variant.ctor) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jonathan Wakely **Opened:** 2025-11-07 **Last modified:** 2025-12-04

**Priority:**Not Prioritized

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#variant.ctor) in [variant.ctor].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#variant.ctor) in [variant.ctor].

**Discussion:**

All `variant` constructors except the last one have a *Throws*: element saying what they're allowed to throw.

This originates from an editorial pull request, where the submitter said:

> "It looks like this defect is an artifact of a change between
> 
> P0088R0
> 
> and
> 
> P0088R1
> 
> .
> Note how in R0 neither one of the
> 
> emplaced_type_t
> 
> /
> 
> emplaced_index_t
> 
> (as they were then called) +
> 
> initializer_list
> 
> constructors have a
> throws clause. In R1 only one of them gained it."

**Previous resolution [SUPERSEDED]:**

> This wording is relative to [N5014](https://wg21.link/N5014).
> 
> 1. Modify 22.6.3.2 [[variant.ctor]](https://wg21.link/variant.ctor), as indicated: template<size_t I, class U, class... Args> constexpr explicit variant(in_place_index_t<I>, initializer_list<U> il, Args&&... args); -35- *Constraints*: (35.1) — `I` is less than `sizeof...(Types)` and (35.2) — `is_constructible_v<T<sub>I</sub>, initializer_list<U>&, Args...>` is `true`. -36- *Effects*: Direct-non-list-initializes the contained value of type `T<sub>I</sub>` with `il, std::forward<Args>(args)...`. -37- *Postconditions*: `index()` is `I`. <ins>-?- *Throws*: Any exception thrown by calling the selected constructor of `T<sub>I</sub>`. </ins> -38- *Remarks*: If `T<sub>I</sub>`’s selected constructor is a constexpr constructor, this constructor is a constexpr constructor.

*[2025-11-11; Jonathan provides improved wording]*

*[2025-12-04; Reflector poll.]*

Set status to Tentatively Ready after six votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5014](https://wg21.link/N5014).

1. Modify 22.6.3.2 [[variant.ctor]](https://wg21.link/variant.ctor), as indicated: constexpr variant() noexcept(*see below*); -2- *Constraints*: `is_default_constructible_v<T<sub>0</sub>>` is `true`. -3- *Effects*: Constructs a `variant` holding a value-initialized value of type `T<sub>0</sub>`. -4- *Postconditions*: `valueless_by_exception()` is `false` and `index()` is `0`. -5- *Throws*: Any exception thrown by the value-initialization of `T<sub>0</sub>`. -6- *Remarks*: […] constexpr variant(const variant&); -7- *Effects*: If `w` holds a value, initializes the `variant` to hold the same alternative as `w` and direct-initializes the contained value with `*GET*<j>(w)`, where `j` is `w.index()`. Otherwise, initializes the `variant` to not hold a value. -8- *Throws*: Any exception thrown by <del>direct-initializating any `T<sub>i</sub>` for all *i*</del> <ins>the initialization of the contained value</ins>. -9- *Remarks*: […] constexpr variant(variant&&) noexcept(*see below*); -10- *Constraints*: `is_move_constructible_v<T<sub>i</sub>>` is `true` for all *i*. -11- *Effects*: If `w` holds a value, initializes the `variant` to hold the same alternative as `w` and direct-initializes the contained value with `*GET*<j>(std::move(w))`, where `j` is `w.index()`. Otherwise, initializes the `variant` to not hold a value. -12- *Throws*: Any exception thrown by <del>move-constructing any `T<sub>i</sub>` for all *i*</del> <ins>the initialization of the contained value</ins>. -13- *Remarks*: […] template<class T> constexpr variant(T&&) noexcept(*see below*); -14- Let `T<sub>j</sub>` be a type that is determined as follows: build an imaginary function `*FUN*(T<sub>i</sub>)` for each alternative type `T<sub>i</sub>` for which `T<sub>i</sub> x[] = {std::forward<T>(t)};` is well-formed for some invented variable `x`. The overload `*FUN*(T<sub>j</sub>)` selected by overload resolution for the expression `*FUN*(std::forward<T>(t))` defines the alternative `T<sub>j</sub>` which is the type of the contained value after construction. -15- *Constraints*: […] -16- *Effects*: Initializes `*this` to hold the alternative type `T<sub>j</sub>` and direct-non-list-initializes the contained value with `std::forward<T>(t)`. -17- *Postconditions*: […] -18- *Throws*: Any exception thrown by the initialization of the <del>selected alternative `T<sub>j</sub>`</del> <ins>contained value</ins>. -19- *Remarks*: […] template<class T, class... Args> constexpr variant(in_place_type_t<T>, Args&&... args); -20- *Constraints*: […] -21- *Effects*: Direct-non-list-initializes the contained value of type `T` with `std::forward<Args>(args)...`. -22- *Postconditions*: […] -23- *Throws*: Any exception thrown by <del>the selected constructor of `T`</del> <ins>the initialization of the contained value</ins>. -24- *Remarks*: […] template<class T, class U, class... Args> constexpr variant(in_place_type_t<T>, initializer_list<U> li, Args&&... args); -25- *Constraints*: […] -26- *Effects*: Direct-non-list-initializes the contained value of type `T` with `il, std::forward<Args>(args)...`. -27- *Postconditions*: […] -28- *Throws*: Any exception thrown by <del>the selected constructor of `T`</del> <ins>the initialization of the contained value</ins>. -29- *Remarks*: […] template<size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, Args&&... args); -30- *Constraints*: (30.1) — `I` is less than `sizeof...(Types)` and (30.2) — `is_constructible_v<T<sub>I</sub>, Args...>` is `true`. -31- *Effects*: Direct-non-list-initializes the contained value of type `T<sub>I</sub>` with `std::forward<Args>(args)...`. -32- *Postconditions*: `index()` is `I`. -33- *Throws*: Any exception thrown by <del>the selected constructor of `T<sub>i</sub>`</del> <ins>the initialization of the contained value</ins>. -34- *Remarks*: If `T<sub>I</sub>`’s selected constructor is a constexpr constructor, this constructor is a constexpr constructor. template<size_t I, class U, class... Args> constexpr explicit variant(in_place_index_t<I>, initializer_list<U> il, Args&&... args); -35- *Constraints*: (35.1) — `I` is less than `sizeof...(Types)` and (35.2) — `is_constructible_v<T<sub>I</sub>, initializer_list<U>&, Args...>` is `true`. -36- *Effects*: Direct-non-list-initializes the contained value of type `T<sub>I</sub>` with `il, std::forward<Args>(args)...`. -37- *Postconditions*: `index()` is `I`. <ins>-?- *Throws*: Any exception thrown by the initialization of the contained value. </ins> -38- *Remarks*: If `T<sub>I</sub>`’s selected constructor is a constexpr constructor, this constructor is a constexpr constructor.

---

### hive::splice can throw bad_alloc

**Section:** 23.3.9.5 [[hive.operations]](https://wg21.link/hive.operations) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jonathan Wakely **Opened:** 2025-11-07 **Last modified:** 2025-12-04

**Priority:**Not Prioritized

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#hive.operations) in [hive.operations].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#hive.operations) in [hive.operations].

**Discussion:**

Moving blocks from the source `hive` to the destination `hive` might require reallocating the array of pointers to blocks, so the *Throws*: element should allow this.

*[2025-12-04; Reflector poll.]*

Set status to Tentatively Ready after seven votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5014](https://wg21.link/N5014).

1. Modify 23.3.9.5 [[hive.operations]](https://wg21.link/hive.operations), as indicated: void splice(hive& x); void splice(hive&& x); -2- *Preconditions*: `get_allocator() == x.get_allocator()` is `true`. -3- *Effects*: If `addressof(x) == this` is `true`, the behavior is erroneous and there are no effects. Otherwise, inserts the contents of `x` into `*this` and `x` becomes empty. Pointers and references to the moved elements of `x` now refer to those same elements but as members of `*this`. Iterators referring to the moved elements continue to refer to their elements, but they now behave as iterators into `*this`, not into `x`. -4- *Throws*: `length_error` if any of `x`'s active blocks are not within the bounds of *`current-limits`* <ins>, as well as any exceptions thrown by the allocator</ins>. -5- *Complexity*: Linear in the sum of all element blocks in `x` plus all element blocks in `*this`. -6- *Remarks*: Reserved blocks in `x` are not transferred into `*this`. If `addressof(x) == this` is `false`, invalidates the past-the-end iterator for both `x` and `*this`.

---

### §[const.wrap.class] "operator decltype(auto)" is ill-formed

**Section:** 21.3.5 [[const.wrap.class]](https://wg21.link/const.wrap.class) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jiang An **Opened:** 2025-11-07 **Last modified:** 2025-12-04

**Priority:**Not Prioritized

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#const.wrap.class) in [const.wrap.class].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#const.wrap.class) in [const.wrap.class].

**Discussion:**

Following the approval of [CWG 1670](https://wg21.link/cwg1670) in Kona 2025, the following declaration in class template `constant_wrapper`, 21.3.5 [[const.wrap.class]](https://wg21.link/const.wrap.class), is ill-formed:

> ```
> constexpr operator decltype(auto)() const noexcept { return value; }
> ```

*[2025-12-04; Reflector poll.]*

Set status to Tentatively Ready after seven votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5014](https://wg21.link/N5014).

1. Modify 21.3.5 [[const.wrap.class]](https://wg21.link/const.wrap.class), class template `constant_wrapper` synopsis, as indicated: […] template<*cw-fixed-value* X, class> struct constant_wrapper : *cw-operators* { static constexpr const auto & value = X.*data*; using type = constant_wrapper; using value_type = typename decltype(X)::*type*; […] constexpr operator decltype(<del>auto</del><ins>value</ins>)() const noexcept { return value; } };

---

### "round_to_nearest" rounding mode is unclear

**Section:** 17.3.4 [[round.style]](https://wg21.link/round.style) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jan Schultke **Opened:** 2025-11-13 **Last modified:** 2026-01-16

**Priority:**Not Prioritized

**Discussion:**

Consider the specification of `round_to_nearest` in 17.3.4 [[round.style]](https://wg21.link/round.style):

> `round_to_nearest` if the rounding style is to the nearest representable value

It is unclear how exact ties are rounded. For example, with this rounding, would a value that is equidistant to zero and `numeric_limits<float>::min()` be rounded towards zero or away from zero? In 17.3.5.2 [[numeric.limits.members]](https://wg21.link/numeric.limits.members), there exists a footnote for `numeric_limits<T>::round_style`:

> 185) Equivalent to `FLT_ROUNDS`. Required by ISO/IEC 10967-1:2012.

In C23 5.2.4.2.2 [Characteristics of floating types `<float.h>`], it is specified that a value of `1` for `FLT_ROUNDS` (which equals `round_to_nearest`) means

> to nearest, ties to even

This is also the default ISO/IEC 60559 rounding mode, and chosen by standard libraries such as libstdc++ for `numeric_limits` under that assumption. Do note that C23 no longer references ISO/IEC 10967 in any normative wording, so presumably, matching `FLT_ROUNDS` values means to match the value that exists in C23, including its meaning.

*[2026-01-16; Reflector poll.]*

Set status to Tentatively Ready after seven votes in favour during reflector poll.

"IEEE 754-2019 talks about what to do in case of a tie for single digit precision types, such as FP4 (E2M1). Will raise this with WG14." [E2M1 is 1 sign bit, 2 exponent bits, 1 explicit mantissa bit]

**Proposed resolution:**

This wording is relative to [N5014](https://wg21.link/N5014).

1. Modify 17.3.4 [[round.style]](https://wg21.link/round.style) as indicated: -1- The rounding mode for floating-point arithmetic is characterized by the values: (1.1) — `round_indeterminate` if the rounding style is indeterminable (1.2) — `round_toward_zero` if the rounding style is toward zero (1.3) — `round_to_nearest` if the rounding style is to the nearest representable value<ins>; if there are two equally near such values, the one with an even least significant digit is chosen</ins> (1.4) — `round_toward_infinity` if the rounding style is toward infinity (1.5) — `round_toward_neg_infinity` if the rounding style is toward negative infinity

---

### Placement operator delete should be constexpr

**Section:** 17.6.3.4 [[new.delete.placement]](https://wg21.link/new.delete.placement) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jakub Jelinek **Opened:** 2025-11-18 **Last modified:** 2025-11-26

**Priority:**Not Prioritized

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#new.delete.placement) in [new.delete.placement].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#new.delete.placement) in [new.delete.placement].

**Discussion:**

The [P2747R2](https://wg21.link/P2747R2) paper made placement operator new constexpr. At that time constexpr exceptions weren't in C++26, so that was all that was needed. But later on when [P3068R5](https://wg21.link/P3068R5) was voted in, the P2747R2 changes look insufficient. The problem is that when you throw from a constructor during operator new, it invokes placement operator delete. And P2747R2 didn't touch that.

This makes it impossible to handle an exception thrown by a placement new-expression during constant evaluation.

*[2025-11-26; Reflector poll.]*

Set status to Tentatively Ready after six votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5014](https://wg21.link/N5014).

1. Modify 17.6.2 [[new.syn]](https://wg21.link/new.syn) as indicated: constexpr void* operator new (std::size_t size, void* ptr) noexcept; constexpr void* operator new[](std::size_t size, void* ptr) noexcept; <ins>constexpr</ins> void operator delete (void* ptr, void*) noexcept; <ins>constexpr</ins> void operator delete[](void* ptr, void*) noexcept;
2. Modify 17.6.3.4 [[new.delete.placement]](https://wg21.link/new.delete.placement) as indicated: constexpr void* operator new(std::size_t size, void* ptr) noexcept; […] constexpr void* operator new[](std::size_t size, void* ptr) noexcept; […] <ins>constexpr</ins> void operator delete(void* ptr, void*) noexcept; -7- *Effects*: Intentionally performs no action. -8- *Remarks*: Default function called when any part of the initialization in a placement *new-expression* that invokes the library's non-array placement operator new terminates by throwing an exception (7.6.2.8 [[expr.new]](https://wg21.link/expr.new)). <ins>constexpr</ins> void operator delete[](void* ptr, void*) noexcept; -9- *Effects*: Intentionally performs no action. -10- *Remarks*: Default function called when any part of the initialization in a placement *new-expression* that invokes the library's array placement operator new terminates by throwing an exception (7.6.2.8 [[expr.new]](https://wg21.link/expr.new)).

---

### <stdatomic.h> should provide ATOMIC_CHAR8_T_LOCK_FREE

**Section:** 32.5.12 [[stdatomic.h.syn]](https://wg21.link/stdatomic.h.syn) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jiang An **Opened:** 2025-11-21 **Last modified:** 2025-12-04

**Priority:**Not Prioritized

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#stdatomic.h.syn) in [stdatomic.h.syn].

**Discussion:**

Currently, `<stdatomic.h>` is specified to provide `atomic_char8_t` but not its corresponding `ATOMIC_CHAR8_T_LOCK_FREE` macro, which is self-inconsistent. Also, given [WG14 N2653](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2653.htm) added `ATOMIC_CHAR8_T_LOCK_FREE` to C's `<stdatomic.h>` in C23, perhaps C++ should do the same thing in the spirit of [P3348R4](https://wg21.link/P3348R4).

*[2025-12-04; Reflector poll.]*

Set status to Tentatively Ready after seven votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5014](https://wg21.link/N5014).

1. Modify 32.5.12 [[stdatomic.h.syn]](https://wg21.link/stdatomic.h.syn), header `<stdatomic.h>` synopsis, as indicated: template<class T> using *std-atomic* = std::atomic<T>; *// exposition only* #define _Atomic(T) *std-atomic*<T> #define ATOMIC_BOOL_LOCK_FREE *see below* #define ATOMIC_CHAR_LOCK_FREE *see below* <ins>#define ATOMIC_CHAR8_T_LOCK_FREE *see below*</ins> #define ATOMIC_CHAR16_T_LOCK_FREE *see below* #define ATOMIC_CHAR32_T_LOCK_FREE *see below* #define ATOMIC_WCHAR_T_LOCK_FREE *see below* #define ATOMIC_SHORT_LOCK_FREE *see below* #define ATOMIC_INT_LOCK_FREE *see below* #define ATOMIC_LONG_LOCK_FREE *see below* #define ATOMIC_LLONG_LOCK_FREE *see below* #define ATOMIC_POINTER_LOCK_FREE *see below* […]

---

### Disallow chrono::duration<const T, P>

**Section:** 30.5.1 [[time.duration.general]](https://wg21.link/time.duration.general) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jonathan Wakely **Opened:** 2025-11-26 **Last modified:** 2026-01-16

**Priority:**Not Prioritized

**Discussion:**

Using a const type as the `rep` for a `chrono::duration` causes various problems but there seems to be no rule preventing it.

The non-const member operators that modify a `duration` don't work if the `rep` type is const, e.g. `duration<const int>::operator++()` is typically ill-formed (unless the implementation chooses to store `remove_cv_t<rep>` as the data member). `hash<duration<const int>>` uses `hash<const int>` which is not enabled, so you can't hash a `duration` with a const rep. Generic code that wants to perform arithmetic with the `rep` type would need to remember to consistently use `remove_cv_t<rep>` to work correctly with const types.

We should just disallow const `rep` types. If you want a non-modifiable duration, use `const duration<R,P>` not `duration<const R, P>`

*[2026-01-16; Reflector poll.]*

Set status to Tentatively Ready after ten votes in favour during reflector poll.

This loses support for `duration<volatile T, P>` but that seems OK.

**Proposed resolution:**

This wording is relative to [N5014](https://wg21.link/N5014).

1. Modify 30.5.1 [[time.duration.general]](https://wg21.link/time.duration.general) as indicated: -2- `Rep` shall be an arithmetic type or a class emulating an arithmetic type. If <ins>a specialization of</ins> `duration` is instantiated with a <ins>cv-qualified type or a specialization of</ins> `duration` <del>type</del> as the argument for the template parameter `Rep`, the program is ill-formed. -3- If `Period` is not a specialization of `ratio`, the program is ill-formed. If `Period::num` is not positive, the program is ill-formed. -4- Members of `duration` do not throw exceptions other than those thrown by the indicated operations on their representations.

---

### Multidimensional arrays are not supported by meta::reflect_constant_array and related functions

**Section:** 21.4.3 [[meta.define.static]](https://wg21.link/meta.define.static) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Tomasz Kamiński **Opened:** 2025-11-27 **Last modified:** 2026-03-06

**Priority:**2

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#meta.define.static) in [meta.define.static].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#meta.define.static) in [meta.define.static].

**Discussion:**

As any array type (even of structural types) is not considered an structural type, per 13.2 [[temp.param]](https://wg21.link/temp.param) p12, any invocation of `reflect_constant_array`/`define_static_array` with a multidimensional array or `span` of arrays is ill-formed due to the *Mandates* in 21.4.3 [[meta.define.static]](https://wg21.link/meta.define.static) p8 that requires range value type to be structural.

As a consequence, `constant_of` currently supports only single-dimensional arrays (`reflect_constant_array` strips outermost extents), while multi-dimensional arrays are rejected.

Furthermore, `define_static_object` currently uses `define_static_array(span(addressof(t), 1)).data()`, for array types. Since for `T[N]` input this creates an multidimensional `T[1][N]` constant parameter object, this function does not support arrays at all. Creating a distinct template parameter object leads to emission of (otherwise unnecessary) additional symbols, and breaks the invariant that for all supported object types `&constant_of(o) == define_static_object(o)`. We should use `reflect_constant_array` for arrays directly.

The *Throws* clause of `reflect_constant_array` was updated to include any exception thrown by iteration over range.

*[2025-12-05; LWG telecon. Wording tweaks]*

*[2025-12-12; LWG telecon. Further wording tweaks]*

*[2026-01-16; Reflector poll.]*

Set priority to 2 after reflector poll.

"The new *Throws*: paragraph implies that `meta::exception` is thrown if a copy constructor of an array element throws, but we want to propagate the thrown exception not catch it an throw a `meta::exception`. Maybe something like:" If evaluation of `reflect_constant` (including evaluation resulting from `reflect_constant_array` invocations) would result in an exception `E` being thrown, then: `E` if an exception was thrown by evaluation of an argument (if any), and `meta::exception` otherwise.

"I suggest:" *Throws*: Any of an exception thrown by any operation on `r` or on iterators and sentinels referring to `r`, an exception thrown by the evaluation of any argument of `reflect_constant` or by any evaluation of `reflect_constant_array`, or `meta::exception` if any invocation of `reflect_constant` would exit via an exception.

**Previous resolution [SUPERSEDED]:**

> This wording is relative to [N5014](https://wg21.link/N5014) amended with changes from LWG [4432](https://cplusplus.github.io/LWG/lwg-defects.html#4432)<sup>[(i)](https://cplusplus.github.io/LWG/issue4432)</sup>.
> 
> 1. Modify 21.4.3 [[meta.define.static]](https://wg21.link/meta.define.static) as indicated: template<ranges::input_range R> consteval info reflect_constant_array(R&& r); -8- Let `<del>T</del><ins>U</ins>` be `ranges::range_value_t<R>` and <ins>`T` be `remove_all_extents_t<U>`</ins> <del>*e<sub>i</sub>* be `static_cast<T>(**it<sub>i</sub>*)`, where *it<sub>i</sub>* is an iterator to the *i<sup>th</sup>* element of `r`</del>. -9- *Mandates*: <ins>(9.1) —</ins> `T` is a structural type (13.2 [[temp.param]](https://wg21.link/temp.param)), <del>`is_constructible_v<T, ranges::range_reference_t<R>>` is `true`, and</del> <ins>(9.2) —</ins> `T` satisfies `copy_constructible`<ins>, and</ins> <ins>(9.3) — if `U` is not an array type, then `is_constructible_v<T, ranges::range_reference_t<R>>` is `true`.</ins> -10- Let `V` be the pack of values of type `info` of the same size as `r`, where the *i<sup>th</sup>* element is <ins>(10.1) — `reflect_constant_array(**it<sub>i</sub>*)` if `U` is an array type,</ins> <ins>(10.2) —</ins> `reflect_constant(<ins>static_cast<T>(**it<sub>i</sub>*)</ins><del>*e<sub>i</sub>*</del>)`<ins> otherwise,</ins> <ins>and *it<sub>i</sub>* is an iterator to the *i<sup>th</sup>* element of `r`</ins>. -11- Let `*P*` be (11.1) — If `sizeof...(V) > 0` is `true`, then the template parameter object (13.2 [[temp.param]](https://wg21.link/temp.param)) of type const `T[sizeof...(V)]` <del>initialized with `{[:V:]...}`</del><ins>, such that `P[*I*]` is template-argument-equivalent (13.6 [[temp.type]](https://wg21.link/temp.type)) to the object represented by `V...[*I*]` for all `*I*` in the range [`0`, `sizeof...(V)`)</ins>. (11.2) — Otherwise, the template parameter object of type `const array<T, 0>` initialized with `{}`. -12- *Returns*: `^^*P*`. -13- *Throws*: <ins>Any exception thrown by operations on `r` or on iterators and sentinels referring to `r`.</ins> Any exception thrown by the evaluation of any <ins>argument of `reflect_constant`.</ins><del>*e<sub>i</sub>*, or</del> `meta::exception` if <del>evaluation of any `reflect_constant(*e<sub>i</sub>*)`</del> <ins>any invocation of `reflect_constant` or `reflect_constant_array`</ins> would exit via an exception. […] template<class T> consteval const remove_cvref_t<T>* define_static_object(T&& t); -15- *Effects*:Equivalent to: using U = remove_cvref_t<T>; if constexpr (meta::is_class_type(^^U)) { return addressof(meta::extract<const U&>(meta::reflect_constant(std::forward<T>(t)))); <ins>} else if constexpr (meta::is_array_type(^^U)) { return addressof(meta::extract<const U&>(meta::reflect_constant_array(std::forward<T>(t))));</ins> } else { return define_static_array(span(addressof(t), 1)).data(); }

*[2026-02-27; LWG telecon. Further wording tweaks]*

Rebased on top of [N5032](https://wg21.link/N5032)

Used alternative suggestion for *Throws* clause.

`define_static_object` now uses `reflect_constant` also for `union` types.

*[2026-03-06; Reflector poll.]*

Set status to Tentatively Ready after five votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify 21.4.3 [[meta.define.static]](https://wg21.link/meta.define.static) as indicated: template<ranges::input_range R> consteval info reflect_constant_array(R&& r); -8- Let `<del>T</del><ins>U</ins>` be `ranges::range_value_t<R>` and <ins>`T` be `remove_all_extents_t<U>`</ins> <del>*e<sub>i</sub>* be `static_cast<T>(**it<sub>i</sub>*)`, where *it<sub>i</sub>* is an iterator to the *i<sup>th</sup>* element of `r`</del>. -9- *Mandates*: <ins>(9.1) —</ins> `T` is a structural type (13.2 [[temp.param]](https://wg21.link/temp.param)), <del>`is_constructible_v<T, ranges::range_reference_t<R>>` is `true`, and</del> <ins>(9.2) —</ins> `T` satisfies `copy_constructible`<ins>, and</ins> <ins>(9.3) — if `U` is not an array type, then `is_constructible_v<T, ranges::range_reference_t<R>>` is `true`.</ins> -10- Let `V` be the pack of values of type `info` of the same size as `r`, where the *i<sup>th</sup>* element is <ins>(10.1) — `reflect_constant_array(**it<sub>i</sub>*)` if `U` is an array type,</ins> <ins>(10.2) —</ins> `reflect_constant(<ins>static_cast<T>(**it<sub>i</sub>*)</ins><del>*e<sub>i</sub>*</del>)`<ins> otherwise,</ins> <ins>and *it<sub>i</sub>* is an iterator to the *i<sup>th</sup>* element of `r`</ins>. -11- Let `*P*` be (11.1) — If `sizeof...(V) > 0` is `true`, then the template parameter object (13.2 [[temp.param]](https://wg21.link/temp.param)) of type const `T[sizeof...(V)]` <del>initialized with `{[:V:]...}`</del><ins>, such that `P[*I*]` is template-argument-equivalent (13.6 [[temp.type]](https://wg21.link/temp.type)) to the object represented by `V...[*I*]` for all `*I*` in the range [`0`, `sizeof...(V)`)</ins>. (11.2) — Otherwise, the template parameter object of type `const array<T, 0>` initialized with `{}`. -12- *Returns*: `^^*P*`. -13- *Throws*: <del>Any exception thrown by the evaluation of any *e<sub>i</sub>*, or `meta::exception` if evaluation of any `reflect_constant(*e<sub>i</sub>*)` would exit via an exception.</del> <ins>Any of </ins> <ins>-13.1- an exception thrown by any operation on `r` or on iterators and sentinels referring to `r`,</ins> <ins>-13.2- an exception thrown by the evaluation of any argument of `reflect_constant` or by any evaluation of `reflect_constant_array`, or</ins> <ins>-13.3- `meta::exception` if any invocation of `reflect_constant` would exit via an exception.</ins> […] template<class T> consteval const remove_cvref_t<T>* define_static_object(T&& t); -15- *Effects*:Equivalent to: using U = remove_cvref_t<T>; if constexpr (meta::is_class_type(^^U)<ins> || meta::is_union_type(^^U)</ins>) { return addressof(meta::extract<const U&>(meta::reflect_constant(std::forward<T>(t)))); <ins>} else if constexpr (meta::is_array_type(^^U)) { return addressof(meta::extract<const U&>(meta::reflect_constant_array(std::forward<T>(t))));</ins> } else { return define_static_array(span(addressof(t), 1)).data(); }

---

### Rename submdspan_extents and submdspan_canonicalize_slices

**Section:** 23.7.3.7 [[mdspan.sub]](https://wg21.link/mdspan.sub) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Tomasz Kamiński **Opened:** 2025-12-16 **Last modified:** 2026-01-16

**Priority:**Not Prioritized

**Discussion:**

Addresses [US 152-243](https://github.com/cplusplus/nbballot/issues/815)
and [PL-008](https://github.com/cplusplus/nbballot/issues/817).

Rename `submdspan_extents` to `subextents` and `submdspan_canonicalize_slices` to `canonical_slices`.

*[2026-01-16; Reflector poll.]*

Set status to Tentatively Ready after six votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify 23.7.3.2 [[mdspan.syn]](https://wg21.link/mdspan.syn) as follows: // 23.7.3.7 [[mdspan.sub]](https://wg21.link/mdspan.sub), submdspan creation template<class OffsetType, class LengthType, class StrideType> struct strided_slice; template<class LayoutMapping> struct submdspan_mapping_result; struct full_extent_t { explicit full_extent_t() = default; }; inline constexpr full_extent_t full_extent{}; template<class IndexType, size_t... Extents, class... SliceSpecifiers> constexpr auto sub<del>mdspan_</del>extents(const extents<IndexType, Extents...>&, SliceSpecifiers...); // [mdspan.sub.canonical], submdspan slice canonicalization template<class IndexType, size_t... Extents, class... Slices> constexpr auto <del>submdspan_canonicalize</del><ins>canonical</ins>_slices(const extents<IndexType, Extents...>& src, Slices... slices);
2. Modify [mdspan.sub.canonical] as follows: `submdspan` slice canonicalization template<class IndexType, size_t... Extents, class... Slices> constexpr auto <del>submdspan_canonicalize</del><ins>canonical</ins>_slices(const extents<IndexType, Extents...>& src, Slices... slices);
3. Modify 23.7.3.7.5 [[mdspan.sub.extents]](https://wg21.link/mdspan.sub.extents) as follows: 23.7.3.7.5 [[mdspan.sub.extents]](https://wg21.link/mdspan.sub.extents) `sub<del>mdspan_</del>extents` function template<class IndexType, size_t... Extents, class... SliceSpecifiers> constexpr auto sub<del>mdspan_</del>extents(const extents<IndexType, Extents...>& src, SliceSpecifiers... raw_slices); -1- Let `slices` be the pack introduced by the following declaration: auto [...slices] = <del>submdspan_canonicalize</del><ins>canonical</ins>_slices(src, raw_slices...)
4. Modify [mdspan.sub.map.sliceable] as follows: -5- *Returns*: An object `smr` of type `SMR` such that -5.1- `smr.mapping.extents() == sub<del>mdspan_</del>extents(m.extents(), valid_slices...)` is `true`; and -5.2- […]
5. Modify 23.7.3.7.6.1 [[mdspan.sub.map.common]](https://wg21.link/mdspan.sub.map.common) as follows: -5- Let `sub_ext` be the result of `sub<del>mdspan_</del>extents(extents(), slices...)` and let `SubExtents` be `decltype(sub_ext)`.
6. Modify 23.7.3.7.7 [[mdspan.sub.sub]](https://wg21.link/mdspan.sub.sub) as follows: -2- Let `slices` be the pack introduced by the following declaration: auto [...slices] = <del>submdspan_canonicalize</del><ins>canonical</ins>_slices(src, raw_slices...)

---

### Specification for some functions of bit reference types seems missing

**Section:** 22.9.2.1 [[template.bitset.general]](https://wg21.link/template.bitset.general), 23.3.14.1 [[vector.bool.pspc]](https://wg21.link/vector.bool.pspc) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jiang An **Opened:** 2025-12-16 **Last modified:** 2026-02-18

**Priority:**Not Prioritized

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#template.bitset.general) in [template.bitset.general].

**Discussion:**

We haven't explicitly specified the return values of `bitset<N>::reference::operator bool()` and `vector<bool, A>::reference::operator bool()`, although the intended return values can be inferred from "a class that simulates a reference to a single bit in the sequence". Moreover, specification for `bitset<N>::reference::operator~` seems completely missing, and the comment "flip the bit" seems misleading. Implementations consistently make the `operator~` return `!operator bool()`.

*[2026-02-18; Reflector poll.]*

Changed resolution to say "the bit referred to by `*this`" instead of "the referred to bit".

Set status to Tentatively Ready after six votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify 22.9.2.1 [[template.bitset.general]](https://wg21.link/template.bitset.general) as indicated: […] *// bit reference* class reference { public: constexpr reference(const reference& x) noexcept; constexpr ~reference(); constexpr reference& operator=(bool x) noexcept; // for b[i] = x; constexpr reference& operator=(const reference& x) noexcept; // for b[i] = b[j]; constexpr const reference& operator=(bool x) const noexcept; constexpr operator bool() const noexcept; // for x = b[i]; constexpr bool operator~() const noexcept; <del>// flips the bit</del> constexpr reference& flip() noexcept; // for b[i].flip(); friend constexpr void swap(reference x, reference y) noexcept; friend constexpr void swap(reference x, bool& y) noexcept; friend constexpr void swap(bool& x, reference y) noexcept; }; […] […] constexpr reference& reference::operator=(bool x) noexcept; constexpr reference& reference::operator=(const reference& x) noexcept; constexpr const reference& reference::operator=(bool x) const noexcept; -6- *Effects*: Sets the bit referred to by `*this` if `bool(x)` is `true`, and clears it otherwise. -7- *Returns*: `*this`. <ins>constexpr reference::operator bool() const noexcept;</ins> <ins>-?- *Returns*: `true` if the value of bit referred to by `*this` is one, `false` otherwise.</ins> <ins>constexpr bool reference::operator~() const noexcept;</ins> <ins>-?- *Returns*: `!bool(*this)`.</ins>
2. Modify 23.3.14.1 [[vector.bool.pspc]](https://wg21.link/vector.bool.pspc) as indicated: […] constexpr reference& reference::operator=(bool x) noexcept; constexpr reference& reference::operator=(const reference& x) noexcept; constexpr const reference& reference::operator=(bool x) const noexcept; -7- *Effects*: Sets the bit referred to by `*this` when `bool(x)` is `true`, and clears it otherwise. -8- *Returns*: `*this`. <ins>constexpr reference::operator bool() const noexcept;</ins> <ins>-?- *Returns*: `true` if the value of the bit referred to by `*this` is one, `false` otherwise.</ins>

---

### constant_wrapper wording problems

**Section:** 21.3.5 [[const.wrap.class]](https://wg21.link/const.wrap.class) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Matthias Wippich **Opened:** 2026-01-07 **Last modified:** 2026-01-16

**Priority:**Not Prioritized

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#const.wrap.class) in [const.wrap.class].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#const.wrap.class) in [const.wrap.class].

**Discussion:**

During resolution of LWG [4383](https://cplusplus.github.io/LWG/lwg-defects.html#4383)<sup>[(i)](https://cplusplus.github.io/LWG/issue4383)</sup> prefix and postfix increment and decrement operators were changed to

> ```
> template<constexpr-param T>
>   constexpr auto operator++(this T) noexcept -> constant_wrapper<++Y>
>     { return {}; }
> template<constexpr-param T>
>   constexpr auto operator++(this T, int) noexcept ->
>     constant_wrapper<Y++> { return {}; }
> template<constexpr-param T>
>   constexpr auto operator--(this T) noexcept -> constant_wrapper<--Y>
>     { return {}; }
> template<constexpr-param T>
>   constexpr auto operator--(this T, int) noexcept ->
>     constant_wrapper<Y--> { return {}; }
> ```

However, we do not actually specify what `Y` is. Additionally, the assignment operator has been changed to

> ```
> template<constexpr-param R>
>   constexpr auto operator=(R) const noexcept
>     -> constant_wrapper<X = R::value> { return {}; }
> ```

This is grammatically not valid C++. The assignment must be parenthesized.

*[2026-01-16; Reflector poll.]*

Set status to Tentatively Ready after five votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify 21.3.5 [[const.wrap.class]](https://wg21.link/const.wrap.class), class template `constant_wrapper` synopsis, as indicated: struct *cw-operators* { *// exposition only* … *// pseudo-mutators* template<*constexpr-param* T> constexpr auto operator++(this T) noexcept -> constant_wrapper<<del>++Y</del> <ins>(++T::value)</ins>> { return {}; } template<*constexpr-param* T> constexpr auto operator++(this T, int) noexcept -> constant_wrapper<<del>Y++</del> <ins>(T::value++)</ins>> { return {}; } template<*constexpr-param* T> constexpr auto operator--(this T) noexcept -> constant_wrapper<<del>--Y</del> <ins>(--T::value)</ins>> { return {}; } template<*constexpr-param* T> constexpr auto operator--(this T, int) noexcept -> constant_wrapper<<del>Y--</del> <ins>(T::value--)</ins>> { return {}; } … }; template<*cw-fixed-value* X, class> struct constant_wrapper : *cw-operators* { static constexpr const auto & value = X.*data*; using type = constant_wrapper; using value_type = decltype(X)::*type*; template<*constexpr-param* R> constexpr auto operator=(R) const noexcept -> constant_wrapper<<ins>(</ins>X = R::value<ins>)</ins>> { return {}; } constexpr operator decltype(auto)() const noexcept { return value; } };

---

### Missing absolute value of init in vector_two_norm and matrix_frob_norm

**Section:** 29.9.13.9 [[linalg.algs.blas1.nrm2]](https://wg21.link/linalg.algs.blas1.nrm2), 29.9.13.12 [[linalg.algs.blas1.matfrobnorm]](https://wg21.link/linalg.algs.blas1.matfrobnorm) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Mark Hoemmen **Opened:** 2026-01-28 **Last modified:** 2026-02-13

**Priority:**Not Prioritized

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#linalg.algs.blas1.nrm2) in [linalg.algs.blas1.nrm2].

**Discussion:**

[This pull request discussion](https://github.com/kokkos/stdBLAS/pull/321#discussion_r2737915864) points out two issues with the current wording of `vector_two_norm`:

1. If `Scalar` is the complex number `1 + i`, then the current wording would make `vector_two_norm` return `sqrt(2i + *nonnegative_real_number*)`. This would have nonzero imaginary part.
2. If `Scalar` is the real number `-1.0`, then the current wording would make `vector_two_norm` return `sqrt(-1.0 + *nonnegative_real_number*)`. If `*nonnegative_real_number*` is less than `1`, then the result would be imaginary.

The analogous issues would also apply to `matrix_frob_norm`. It's acceptable for the return type `Scalar` to be `complex`. However, the point of letting `init` be nonzero is to support computing the 2-norm of a vector (or the Frobenius norm of a matrix) in multiple steps. The value of `init` should thus always represent a valid 2-norm (or Frobenius norm) result. There are two ways to fix this:

1. Impose a precondition on `init`, that it have nonnegative real part and zero imaginary part.
2. Change the *Returns* element to take the absolute value of `init`. (The 29.9 [[linalg]](https://wg21.link/linalg) clause generally uses "absolute value" to mean the magnitude of a complex number, or the absolute value of a non-complex number.)

We offer (2) as the Proposed Fix, as it is consistent with the approach we took for fixing LWG [4136](https://cplusplus.github.io/LWG/lwg-defects.html#4136)<sup>[(i)](https://cplusplus.github.io/LWG/issue4136)</sup>.

*[2026-02-13; Reflector poll.]*

Set status to Tentatively Ready after six votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify 29.9.13.9 [[linalg.algs.blas1.nrm2]](https://wg21.link/linalg.algs.blas1.nrm2) as indicated: [*Drafting note*: As a drive-by fix the missing closing parenthesis of the `decltype` form has been added.] template<*in-vector* InVec, *scalar* Scalar> Scalar vector_two_norm(InVec v, Scalar init); template<class ExecutionPolicy, *in-vector* InVec, *scalar* Scalar> Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init); -1- [*Note 1*: These functions correspond to the BLAS function `xNRM2`[17]. — *end note*] -2- *Mandates*: `InVec::value_type` and `Scalar` are either a floating-point type, or a specialization of `complex`. Let `a` be `*abs-if-needed*(declval<typename InVec::value_type>())` <ins>and let `init_abs` be `*abs-if-needed*(init)`</ins>. Then, `decltype(init<ins>_abs * init_abs</ins> + a * a<ins>)</ins>` is convertible to `Scalar`. -3- *Returns*: The square root of the sum <del>of the square of `init` and the squares of the absolute values of the elements of `v`.</del><ins>whose terms are the following:</ins> <ins>(3.1) — the square of the absolute value of `init`, and</ins> <ins>(3.2) — the squares of the absolute values of the elements of `v`.</ins> [*Note 2*: For `init` equal to zero, this is the Euclidean norm (also called 2-norm) of the vector `v`. — *end note*] -4- *Remarks*: If `Scalar` has higher precision than `InVec::value_type`, then intermediate terms in the sum use `Scalar`'s precision or greater.
2. Modify 29.9.13.12 [[linalg.algs.blas1.matfrobnorm]](https://wg21.link/linalg.algs.blas1.matfrobnorm) as indicated: [*Drafting note*: As a drive-by fix one spurious `InVec` has been changed to `InMat`] template<*in-matrix* InMat, *scalar* Scalar> Scalar matrix_frob_norm(InMat A, Scalar init); template<class ExecutionPolicy, *in-matrix* InMat, *scalar* Scalar> Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init); -2- *Mandates*: `<del>InVec</del><ins>InMat</ins>::value_type` and `Scalar` are either a floating-point type, or a specialization of `complex`. Let `a` be `*abs-if-needed*(declval<typename InMat::value_type>())` <ins>and let `init_abs` be `*abs-if-needed*(init)`</ins>. Then, `decltype(init<ins>_abs * init_abs</ins> + a * a)` is convertible to `Scalar`. -3- *Returns*: The square root of the sum <del>of the squares of `init` and the absolute values of the elements of `A`.</del><ins>whose terms are the following:</ins> <ins>(3.1) — the square of the absolute value of `init`, and</ins> <ins>(3.2) — the squares of the absolute values of the elements of `A`.</ins> [*Note 2*: For `init` equal to zero, this is the Frobenius norm of the matrix `A`. — *end note*] -4- *Remarks*: If `Scalar` has higher precision than `InMat::value_type`, then intermediate terms in the sum use `Scalar`'s precision or greater.

---

### data_member_spec should throw for cv-qualified unnamed bit-fields

**Section:** 21.4.16 [[meta.reflection.define.aggregate]](https://wg21.link/meta.reflection.define.aggregate) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Marek Polacek **Opened:** 2026-02-05 **Last modified:** 2026-02-27

**Priority:**Not Prioritized

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#meta.reflection.define.aggregate) in [meta.reflection.define.aggregate].

**Discussion:**

[DR 2229](https://cplusplus.github.io/CWG/issues/cwg_defects.html#2229) changed 11.4.10 [[class.bit]](https://wg21.link/class.bit) p2 to say:

> An unnamed bit-field shall not be declared with a *cv*-qualified type.

It follows that `define_aggregate` should have the same limitation, and thus in:

> ```
> #include <meta>
> 
> constexpr auto d1 = std::meta::data_member_spec(^^const int, { .bit_width = 1 });
> constexpr auto d2 = std::meta::data_member_spec(^^volatile int, { .bit_width = 1 });
> constexpr auto d3 = std::meta::data_member_spec(^^const volatile int, { .bit_width = 1 });
> ```

all three `data_member_spec` should throw.

*[2026-02-27; Reflector poll.]*

Set status to Tentatively Ready after 8 votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify 21.4.16 [[meta.reflection.define.aggregate]](https://wg21.link/meta.reflection.define.aggregate) as indicated: consteval info data_member_spec(info type, data_member_options options); -4- *Returns*: […] -5- *Throws*: `meta::exception` unless the following conditions are met: (5.1) — `dealias(type)` represents either an object type or a reference type; (5.2) — if `options.name` contains a value, then: […] (5.3) — if `options.name` does not contain a value, then `options.bit_width` contains a value; (5.4) — if `options.bit_width` contains a value `*V*`, then (5.4.1) — `is_integral_type(type) || is_enum_type(type)` is `true`, (5.4.2) — `options.alignment` does not contain a value, (5.4.3) — `options.no_unique_address` is `false`, (5.4.4) — `*V*` is not negative, and (5.4.5) — if `*V*` equals `0`, then `options.name` does not contain a value; and <ins>(5.4.?) — if `options.name` does not contain a value, then `is_const(type) || is_volatile(type)` is `false`; and</ins> (5.5) — if `options.alignment` contains a value, it is an alignment value (6.8.3 [[basic.align]](https://wg21.link/basic.align)) not less than `alignment_of(type)`.

---

### Clarify that std::format transcodes for std::wformat_strings

**Section:** 28.5.2.2 [[format.string.std]](https://wg21.link/format.string.std) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Jan Schultke **Opened:** 2026-02-12 **Last modified:** 2026-02-27

**Priority:**Not Prioritized

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#format.string.std) in [format.string.std].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#format.string.std) in [format.string.std].

**Discussion:**

The current wording in 28.5.2.2 [[format.string.std]](https://wg21.link/format.string.std) paragraph 20 suggests that the expression `format(L"{}", 0)` could produce a garbage or malformed string:

> […] Formatting is done as if by calling `to_chars` as specified and copying the output through the output iterator of the format context.

It is not stated that transcoding takes place, so a plausible interpretation is that the output of `to_chars` is copied to the output iterator directly. If the ordinary literal encoding is, say, EBCDIC and the wide literal encoding is, say, UTF-32, simply converting `char` to `wchar_t` is not meaningful. During the 2026-02-11 SG16 Telecon, when reviewing [P3876R0](https://wg21.link/P3876R0), SG16 examined this issue and concluded that transcoding is intended here, affirmed by the author of [P0645R10](https://wg21.link/P0645R10) Text Formatting. An LWG issue was requested.

*[2026-02-27; Reflector poll.]*

Set status to Tentatively Ready after eight votes in favour during reflector poll.

[P3876](https://wg21.link/P3876) would address that, but we need to clarify the wording for existing standards.

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Modify 28.5.2.2 [[format.string.std]](https://wg21.link/format.string.std) as indicated: [*Drafting note*: 28.5.6.5 [[format.string.escaped]](https://wg21.link/format.string.escaped) paragraph 2 similarly references the wide literal encoding (as the associated character encoding for `charT = wchar_t`. ] -20- The meaning of some non-string presentation types is defined in terms of a call to `to_chars`. In such cases, let `[first, last)` be a range large enough to hold the `to_chars` output and value be the formatting argument value. Formatting is done as if by calling `to_chars` as specified <ins>, transcoding the `to_chars` output to the wide literal encoding if `charT` is `wchar_t`,</ins> and copying the output through the output iterator of the format context. [*Note 7*: Additional padding and adjustments are performed prior to copying the output through the output iterator as specified by the format specifiers. — *end note*]

---

### constant_wrapper should assign to value

**Section:** 21.3.5 [[const.wrap.class]](https://wg21.link/const.wrap.class) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Tomasz Kamiński **Opened:** 2026-02-17 **Last modified:** 2026-02-27

**Priority:**Not Prioritized

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#const.wrap.class) in [const.wrap.class].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#const.wrap.class) in [const.wrap.class].

**Discussion:**

During resolution of LWG [4383](https://cplusplus.github.io/LWG/lwg-defects.html#4383)<sup>[(i)](https://cplusplus.github.io/LWG/issue4383)</sup> assignment operator of `constant_wrapper`, was changed to:

> ```
> template<constexpr-param R>
>   constexpr auto operator=(R) const noexcept -> constant_wrapper<X = R::value> { return {}; }
> ```

This is incorrect (and inconsistent with other operators), as we assign to `X` that is object of specialization of exposition only `*cw-fixed-value*`, instead of `value`.

*[2026-02-27; Reflector poll.]*

Set status to Tentatively Ready after 9 votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032) with changes from [4500](https://cplusplus.github.io/LWG/lwg-active.html#4500)<sup>[(i)](https://cplusplus.github.io/LWG/issue4500)</sup>.

1. Modify 21.3.5 [[const.wrap.class]](https://wg21.link/const.wrap.class), class template `constant_wrapper` synopsis, as indicated: template<*cw-fixed-value* X, class> struct constant_wrapper : *cw-operators* { static constexpr const auto & value = X.*data*; using type = constant_wrapper; using value_type = decltype(X)::*type*; template<*constexpr-param* R> constexpr auto operator=(R) const noexcept -> constant_wrapper<(<ins>value</ins><del>X</del> = R::value)> { return {}; } constexpr operator decltype(auto)() const noexcept { return value; } };

---

### task's final_suspend should move the result

**Section:** 33.13.6.5 [[task.promise]](https://wg21.link/task.promise) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Dietmar Kühl **Opened:** 2026-02-21 **Last modified:** 2026-02-27

**Priority:**Not Prioritized

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#task.promise) in [task.promise].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#task.promise) in [task.promise].

**Discussion:**

In 33.13.6.5 [[task.promise]](https://wg21.link/task.promise) p6.3 the `*result` is passed to `set_value` without `std::move`ing: `set_value(std::move(*RCVR*(*this)), **result*)`. Once `set_value` is called the operation state object where `*result*` is stored just gets destroyed. The second argument to `set_value` should be `std::move(**result*)`.

*[2026-02-27; Reflector poll.]*

Set status to Tentatively Ready after 6 votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Change 33.13.6.5 [[task.promise]](https://wg21.link/task.promise) p6.3 to `std::move` the `**result*`: auto final_suspend() noexcept; -6- *Returns*: An awaitable object of unspecified type (7.6.2.4 [[expr.await]](https://wg21.link/expr.await)) whose member functions arrange for the completion of the asynchronous operation associated with `*STATE*(*this)` by invoking: -6.1- -- `set_error(std::move(*RCVR*(*this)), std::move(e))` if `*errors*.index()` is greater than zero and `e` is the value held by `*errors*`, otherwise -6.2- -- `set_value(std::move(*RCVR*(*this)))` if `is_void<T>` is `true`, and otherwise -6.3- -- `set_value(std::move(*RCVR*(*this)), <ins>std::move(</ins>**result*<ins>)</ins>)`.

---

### await_transform needs to use as_awaitable

**Section:** 33.13.6.5 [[task.promise]](https://wg21.link/task.promise) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Dietmar Kühl **Opened:** 2026-02-21 **Last modified:** 2026-02-27

**Priority:**Not Prioritized

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#task.promise) in [task.promise].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#task.promise) in [task.promise].

**Discussion:**

In the `await_transform` overload for `change_coroutine_scheduler` the `return` statement repeats the function name instead of using `as_awaitable`. The `return` statement needs to be fixed. The change may be editorial.

Note that [P3941](https://wg21.link/P3941) recommends removing `change_coroutine_scheduler` and the corresponding overload of `await_transform` entirely.

*[2026-02-27; Reflector poll.]*

Set status to Tentatively Ready after 7 votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Change 33.13.6.5 [[task.promise]](https://wg21.link/task.promise) p10 to use `as_awaitable` in the *Effects* clause: template<class Sch> auto await_transform(change_coroutine_scheduler<Sch> sch) noexcept; -10- *Effects*: Equivalent to: return <del>await_transform</del><ins>as_awaitable</ins>(just(exchange(*SCHED*(*this), scheduler_type(sch.scheduler))), *this);

---

### task needs get_completion_signatures()

**Section:** 33.13.6.2 [[task.class]](https://wg21.link/task.class) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Dietmar Kühl **Opened:** 2026-02-21 **Last modified:** 2026-02-27

**Priority:**Not Prioritized

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#task.class) in [task.class].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#task.class) in [task.class].

**Discussion:**

The changes made by [P3164](https://wg21.link/P3164) mean that it isn't sufficient to have a `completion_signatures` type alias in the `task` class. Instead, it needs to have a `static consteval get_completion_signatures()` member function that returns the completion signatures. Instead of defining a type alias, the function can return the same type.

*[2026-02-27; Reflector poll.]*

Set status to Tentatively Ready after 6 votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Change the `task` synopsis in 33.13.6.2 [[task.class]](https://wg21.link/task.class) to not have a `completion_signatures` type alias, but instead have a `static consteval get_completion_signatures()` member function that returns the completion signatures: namespace std::execution { template<class T = void, class Environment = env<>> class task { // [task.state] template<receiver Rcvr> class state; // *exposition only* public: using sender_concept = sender_t; <del>using completion_signatures = *see below*;</del> using allocator_type = *see below*; using scheduler_type = *see below*; using stop_source_type = *see below*; using stop_token_type = decltype(declval<stop_source_type>().get_token()); using error_types = *see below*; // [task.promise] class promise_type; task(task&&) noexcept; ~task(); <ins>template<class Self, class... Env> static consteval auto get_completion_signatures();</ins> template<receiver Rcvr> state<Rcvr> connect(Rcvr&& rcvr) &&; private: coroutine_handle<promise_type> handle; // *exposition only* }; }
2. Remove 33.13.6.2 [[task.class]](https://wg21.link/task.class) paragraph 4 (the specification moves to 33.13.6.3 [[task.members]](https://wg21.link/task.members)): <del> -4- The type alias `completion_signatures` is a specialization of `execution::completion_signatures` with the template arguments (in unspecified order): </del> <del> -4.1- -- `set_value_t()` if `T` is `void`, and `set_value_t(T)` otherwise; </del> <del> -4.2- -- template arguments of the specialization of `execution::completion_signatures` denoted by `error_types`; and </del> <del> -4.3- -- `set_stopped_t()`. </del>
3. Add a new paragraph to 33.13.6.3 [[task.members]](https://wg21.link/task.members) before the specification of the `connect` member function, with the specification of the new `get_completion_signatures` member function: <ins> <ins>template<class Self, class... Env> static consteval auto get_completion_signatures();</ins> </ins> <ins> -?- Let the type `C` be a specialization of `execution::completion_signatures` with the template arguments (in unspecified order): </ins> <ins> -?.1- -- `set_value_t()` if `T` is `void`, and `set_value_t(T)` otherwise; </ins> <ins> -?.2- -- template arguments of the specialization of `execution::completion_signatures` denoted by `error_types`; and </ins> <ins> -?.3- -- `set_stopped_t()`. </ins> <ins> -?- *Returns*: `C()`. </ins>

---

### task::promise_type::await_transform declaration and definition mismatch

**Section:** 33.13.6.5 [[task.promise]](https://wg21.link/task.promise) **Status:** [Tentatively Ready](https://cplusplus.github.io/LWG/lwg-active.html#Ready) **Submitter:** Dietmar Kühl **Opened:** 2026-02-21 **Last modified:** 2026-02-27

**Priority:**Not Prioritized

**View other** [active issues](https://cplusplus.github.io/LWG/lwg-index-open.html#task.promise) in [task.promise].

**View all other** [issues](https://cplusplus.github.io/LWG/lwg-index.html#task.promise) in [task.promise].

**Discussion:**

The declarations of `await_transform` mismatch between the synopsis in 33.13.6.5 [[task.promise]](https://wg21.link/task.promise) and the definition in 33.13.6.5 [[task.promise]](https://wg21.link/task.promise) paragraph 9:

```
    template<class A>
      auto await_transform(A&& a);
    template<class Sch>
      auto await_transform(change_coroutine_scheduler<Sch> sch);
```

vs.

```
    template<sender Sender>
      auto await_transform(Sender&& sndr) noexcept;
    template<class Sch>
      auto await_transform(change_coroutine_scheduler<Sch> sch) noexcept;
```

The declaration should be fixed to match the definition.

*[2026-02-27; Reflector poll.]*

Set status to Tentatively Ready after six votes in favour during reflector poll.

**Proposed resolution:**

This wording is relative to [N5032](https://wg21.link/N5032).

1. Change the declarations of `await_transform` in the synopsis of `promise_type` in 33.13.6.5 [[task.promise]](https://wg21.link/task.promise) to match the definition in 33.13.6.5 [[task.promise]](https://wg21.link/task.promise) p9 except for omitting the `noexcept` specifier: namespace std::execution { template<class T, class Environment> class task<T, Environment>::promise_type { public: ... template<class E> unspecified yield_value(with_error<E> error); template<<del>class A</del><ins>sender Sender</ins>> auto await_transform(<del>A&& a</del><ins>Sender&& sndr</ins>); template<class Sch> auto await_transform(change_coroutine_scheduler<Sch> sch); *unspecified* get_env() const noexcept; ... }; }
2. Remove the `noexcept` specifier from the declarations of `await_transform` in the definition of `promise_type` in 33.13.6.5 [[task.promise]](https://wg21.link/task.promise) p9: template<sender Sender> auto await_transform(Sender&& sndr) <del>noexcept</del>; -9- *Returns*: If `same_as<inline_scheduler, scheduler_type>` is `true` returns `as_awaitable(std::forward<Sender>(sndr), *this);` otherwise returns `as_awaitable(affine_on(std::forward<Sender>(sndr), *SCHED*(*this)), *this)`. template<class Sch> auto await_transform(change_coroutine_scheduler<Sch> sch) <del>noexcept</del>; -10- *Effects*: Equivalent to: return await_transform(just(exchange(*SCHED(*this)*, scheduler_type(sch.scheduler))), *this);
