Doc. no. | P3742R0 |
Date: | 2025-06-13 |
Audience: | WG21 |
Reply to: | Jonathan Wakely <[email protected]> |
schedule_from
isn't starting the schedule sender if decay-copying results throwsenable-sender
should be a variable templateget-state
functions are incorrectas-sndr2(Sig)
in [exec.let] is incompletelet_[*].transform_env
is specified in terms of the let_*
sender itself instead of its childconnect(sndr, rcvr)
that rcvr
expression is only evaluated oncedefault_domain::transform_env
should be returning FWD-ENV(env)
ostream::sentry
destructor should handle exceptionsoperation_state
concept can be simplifiedwith-await-transform::await_transform
should not use a deduced return typemdspan
layout mapping requirements for rank == 0
expected
constructor from a single value missing a constraintnoexcept
operator in [exec.when.all]datapar::chunk<N>
should use simd-size-type
instead of size_t
datapar::resize
does not resizestd::erase
for hive
should specify return type as
<hive>
doesn't provide std::begin/end
cache_latest_view
and to_input_view
miss reserve_hint
chunk_view::outer-iterator::value_type
should provide reserve_hint
flat_map
's transparent comparator no longer works for string literalsranges::distance
does not work with volatile iteratorscounted_iterator
and default_sentinel_t
should be noexcept
<stdbit.h>
is not yet freestandingschedule_from
isn't starting the schedule sender if decay-copying results throwsSection: 33.9.12.5 [exec.schedule.from] Status: Ready Submitter: Eric Niebler Opened: 2025-02-03 Last modified: 2025-02-13
Priority: 1
View other active issues in [exec.schedule.from].
View all other issues in [exec.schedule.from].
Discussion:
Imported from cplusplus/sender-receiver #304.
33.9.12.5 [exec.schedule.from]/p11 specifies schedule_from
's completion operation as follows:
[]<class Tag, class... Args>(auto, auto& state, auto& rcvr, Tag, Args&&... args) noexcept
-> void {
using result_t = decayed-tuple<Tag, Args...>;
constexpr bool nothrow = is_nothrow_constructible_v<result_t, Tag, Args...>;
try {
state.async-result.template emplace<result_t>(Tag(), std::forward<Args>(args)...);
} catch (...) {
if constexpr (!nothrow) {
set_error(std::move(rcvr), current_exception());
return;
}
}
start(state.op-state);
};
so if emplacing the result tuple throws, set_error
is immediately called on the downstream receiver. no attempt is made to post the completion to the specified scheduler. this is probably not the right behavior.
Suggested resolution
The right thing, i think, is to catch the exception, emplace the exception_ptr
into the async-result
variant, and then start the schedule operation, as shown below:
[]<class Tag, class... Args>(auto, auto& state, auto& rcvr, Tag, Args&&... args) noexcept
-> void {
using result_t = decayed-tuple<Tag, Args...>;
constexpr bool nothrow = is_nothrow_constructible_v<result_t, Tag, Args...>;
try {
state.async-result.template emplace<result_t>(Tag(), std::forward<Args>(args)...);
} catch(...) {
if constexpr (!nothrow)
state.async-result.template emplace<tuple<set_error_t, exception_ptr>>(set_error, current_exception());
}
start(state.op-state);
}
we also need to change how we specify the variant type of
state.async-result
:
LetSigs
be a pack of the arguments to thecompletion_signatures
specialization named bycompletion_signatures_of_t<child-type<Sndr>, env_of_t<Rcvr>>
. Letas-tuple
be an alias templatethat transforms a completion signaturesuch thatTag(Args...)
into the tuple specializationdecayed-tuple<Tag, Args...>
.as-tuple<Tag(Args...)>
denotes the tuple specializationdecayed-tuple<Tag, Args...>
, and letis-nothrow-decay-copy-sig
be a variable template such thatis-nothrow-decay-copy-sig<Tag(Args...)>
is a core constant expression of typebool const
and whose value istrue
if the typesArgs...
are all nothrow decay-copyable, andfalse
otherwise. Leterror-completion
be a pack consisting of the typeset_error_t(exception_ptr)
if(is-nothrow-decay-copy-sig<Sigs> &&...)
isfalse
, and an empty pack otherwise. Thenvariant_t
denotes the typevariant<monostate, as-tuple<Sigs>..., error-completion...>
, except with duplicate types removed.
[This touches the same text as LWG 4203(i).]
[2025-02-07; Reflector poll]
Set priority to 1 after reflector poll.
[Hagenberg 2025-02-11; LWG]
Direction seems right. Decay-copyable is not a defined term.
[2025-02-12 Tim adds PR]
This also corrects the issue that nothrow
is currently relying
on the unspecified exception specification of tuple
's constructor.
[Hagenberg 2025-02-12; move to Ready]
Proposed resolution:
This wording is relative to N5001.
-8- Let
Sigs
be a pack of the arguments to thecompletion_signatures
specialization named bycompletion_signatures_of_t<child-type<Sndr>, env_of_t<Rcvr>>
. Letas-tuple
be an alias templatethat transforms a completion signaturesuch thatTag(Args...)
into the tuple specializationdecayed-tuple<Tag, Args...>
.as-tuple<Tag(Args...)>
denotes the typedecayed-tuple<Tag, Args...>
, and letis-nothrow-decay-copy-sig
be a variable template such thatauto(is-nothrow-decay-copy-sig<Tag(Args...)>)
is a constant expression of typebool
and equal to(is_nothrow_constructible_v<decay_t<Args>, Args> && ...)
. Leterror-completion
be a pack consisting of the typeset_error_t(exception_ptr)
if(is-nothrow-decay-copy-sig<Sigs> &&...)
isfalse
, and an empty pack otherwise. Thenvariant_t
denotes the typevariant<monostate, as-tuple<Sigs>..., error-completion...>
, except with duplicate types removed.
Modify 33.9.12.5 [exec.schedule.from] p11 as indicated:
-11- The member
impls-for<schedule_from_t>::complete
is initialized with a callable object equivalent to the following lambda:[]<class Tag, class... Args>(auto, auto& state, auto& rcvr, Tag, Args&&... args) noexcept -> void { using result_t = decayed-tuple<Tag, Args...>; constexpr bool nothrow =
is_nothrow_constructible_v<result_t, Tag, Args...>(is_nothrow_constructible_v<decay_t<Args>, Args> && ...); try { state.async-result.template emplace<result_t>(Tag(), std::forward<Args>(args)...); } catch (...) { if constexpr (!nothrow){state.async-result.template emplace<tuple<set_error_t, exception_ptr>>(set_error, current_exception());set_error(std::move(rcvr), current_exception());return;}} start(state.op-state); };
enable-sender
should be a variable templateSection: 33.9.3 [exec.snd.concepts] Status: Ready Submitter: Eric Niebler Opened: 2025-02-03 Last modified: 2025-02-12
Priority: 1
Discussion:
Imported from cplusplus/sender-receiver #305 and cplusplus/sender-receiver #306.
We require an opt-in to satisfy the sender
concept.
Making your type awaitable with an empty environment is one way to opt in.
If your awaitable requires an environment, you have two options:
sender_concept
typedef, orenable_sender
for your awaitable type.enable_sender
variable template was turned into
an exposition-only enable-sender
concept.
We should roll back that change.
[2025-02-07; Reflector poll]
Set priority to 1 after reflector poll.
[Hagenberg 2025-02-11; move to Ready]
Proposed resolution:
This wording is relative to N5001.
template<class Sndr> concept is-sender = // exposition only derived_from<typename Sndr::sender_concept, sender_t>; template<class Sndr> concept enable-sender = // exposition only is-sender<Sndr> || is-awaitable<Sndr, env-promise<empty_env>>; // [exec.awaitable] template<class Sndr> inline constexpr bool enable_sender = enable-sender<Sndr>; template<class Sndr> concept sender =
bool(enable-senderenable_sender<remove_cvref_t<Sndr>>)&& requires (const remove_cvref_t<Sndr>& sndr) { { get_env(sndr) } -> queryable; } && move_constructible<remove_cvref_t<Sndr>> && constructible_from<remove_cvref_t<Sndr>, Sndr>;…
-2- Given a subexpression
sndr
, […]-?- Remarks: Pursuant to 16.4.5.2.1 [namespace.std], users may specialize
enable_sender
totrue
for cv-unqualified program-defined types that modelsender
, andfalse
for types that do not. Such specializations shall be usable in constant expressions (7.7 [expr.const]) and have typeconst bool
.
get-state
functions are incorrectSection: 33.9.12.5 [exec.schedule.from] Status: Ready Submitter: Eric Niebler Opened: 2025-02-03 Last modified: 2025-02-12
Priority: 1
View other active issues in [exec.schedule.from].
View all other issues in [exec.schedule.from].
Discussion:
Imported from: cplusplus/sender-receiver #313 and cplusplus/sender-receiver #314.
33.9.12.5 [exec.schedule.from] p6 reads:
The memberThe constraint should account for the fact that the child sender will be connected withimpls-for<schedule_from_t>::get-state
is initialized with a callable object equivalent to the following lambda:[]<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept(see below) requires sender_in<child-type<Sndr>, env_of_t<Rcvr>> {
FWD-ENV(get_env(rcvr))
.
[ The resolution touches some of the same text as LWG 4198(i), but without conflicting. ]
Imported from: cplusplus/sender-receiver #315.
33.9.12.11 [exec.when.all] p6 reads:
The memberThe problem is in (6.3). It should be forwarding onimpls-for<when_all_t>::get-env
is initialized with a callable object equivalent to the following lambda expression:Returns an object[]<class State, class Rcvr>(auto&&, State& state, const Receiver& rcvr) noexcept { return see below; }
e
such that
- (6.1) —
decltype(e)
modelsqueryable
, and- (6.2) —
e.query(get_stop_token)
is expression-equivalent tostate.stop-src.get_token()
, and- (6.3) — given a query object
q
with type other than cvstop_token_t
,e.query(q)
is expression-equivalent toget_env(rcvr).query(q)
.
forwarding-query
's
to get_env(rcvr)
but is is instead forwarding all queries.
Imported from: cplusplus/sender-receiver #316.
The child senders should only see the parent's queries if they are forwarding queries.
Imported from: cplusplus/sender-receiver #311.
33.9.12.13 [exec.stopped.opt]/para 3 reads:
Letthe test forsndr
andenv
be subexpressions such thatSndr
isdecltype((sndr))
andEnv
isdecltype((env))
. Ifsender-for<Sndr, stopped_as_optional_t>
isfalse
, or if the typesingle-sender-value-type<Sndr, Env>
is ill-formed orvoid
, then the expressionstopped_as_optional.transform_sender(sndr, env)
is ill-formed; otherwise, it is equivalent to:
single-sender-value-type<Sndr, Env>
is incorrect.
It should be testing its child for single-sender-ness.
In addition, it should be applying FWD-ENV-T
to Env
so that only forwarding queries are forwarded.
[2025-02-07; Reflector poll]
Set priority to 1 after reflector poll.
[Hagenberg 2025-02-11; move to Ready]
Proposed resolution:
This wording is relative to N5001.
-2- For a queryable objectenv
,FWD-ENV(env)
is an expression whose type satisfiesqueryable
such that for a query objectq
and a pack of subexpressionsas
, the expressionFWD-ENV(env).query(q, as...)
is ill-formed ifforwarding_query(q)
isfalse
; otherwise, it is expression-equivalent toenv.query(q, as...)
. The typeFWD-ENV-T(Env)
isdecltype(FWD-ENV(declval<Env>()))
.
-6- The memberimpls-for<schedule_from_t>::get-state
is initialized with a callable object equivalent to the following lambda:[]<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept(see below) requires sender_in<child-type<Sndr>, FWD-ENV-T(env_of_t<Rcvr>)> {
…
-8- Let
Sigs
be a pack of the arguments to thecompletion_signatures
specialization named bycompletion_signatures_of_t<child-type<Sndr>, FWD-ENV-T(env_of_t<Rcvr>)>
. Letas-tuple
be an alias template that transforms a completion signatureTag(Args...)
into the tuple specializationdecayed-tuple<Tag, Args...>
. Thenvariant_t
denotes the typevariant<monostate, as-tuple<Sigs>...>
, except with duplicate types removed.
-6- Let
receiver2
denote the following exposition-only class template:Invocation of the functionnamespace std::execution { … }
receiver2::get_env
returns an objecte
such that
- (6.1) —
decltype(e)
modelsqueryable
and- (6.2) — given a query object
q
, the expressione.query(q)
is expression-equivalent toenv.query(q)
if that expression is valid,; otherwise, if the type ofq
satisfiesforwarding-query
,e.query(q)
is expression-equivalent toget_env(rcvr).query(q)
; otherwise,e.query(q)
is ill-formed.-7-
impls-for<decayed-typeof<let-cpo>>::get-state
is initialized with a callable object […]-8- Let
Sigs
be a pack of the arguments to thecompletion_signatures
specialization named bycompletion_signatures_of_t<child-type<Sndr>, FWD-ENV-T(env_of_t<Rcvr>)>
. LetLetSigs
be a pack of those types inSigs
with a return type ofdecayed-typeof<set-cpo>
. Letas-tuple
be an alias template such thatas-tuple<Tag(Args...)>
denotes the typedecayed-tuple<Args...>
. Thenargs_variant_t
denotes the typevariant<monostate, as-tuple<LetSigs>...>
except with duplicate types removed.
-6- The member
impls-for<when_all_t>::get-env
is initialized with a callable object equivalent to the following lambda expression:Returns an object[]<class State, class Rcvr>(auto&&, State& state, const Receiver& rcvr) noexcept { return see below; }
e
such that
- (6.1) —
decltype(e)
modelsqueryable
, and- (6.2) —
e.query(get_stop_token)
is expression-equivalent tostate.stop-src.get_token()
, and- (6.3) — given a query object
q
with type other than cvstop_token_t
and whose type satisfiesforwarding-query
,e.query(q)
is expression-equivalent toget_env(rcvr).query(q)
.-7- The member
impls-for<when_all_t>::get-state
is initialized with a callable object equivalent to the following lambda expression:where e is the expression[]<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept(e) -> decltype(e) { return e; }
andstd::forward<Sndr>(sndr).apply(make-state<Rcvr>())
make-state
is the following exposition-only class template:…template<class Sndr, class Env> concept max-1-sender-in = sender_in<Sndr, Env> && // exposition only (tuple_size_v<value_types_of_t<Sndr, Env, tuple, tuple>> <= 1); enum class disposition { started, error, stopped }; // exposition only template<class Rcvr> struct make-state { template<max-1-sender-in<FWD-ENV-T(env_of_t<Rcvr>)>... Sndrs>
-8- Let
copy_fail
beexception_ptr
if […]-9- The alias
values_tuple
denotes the typeif that type is well-formed; otherwise,tuple<value_types_of_t<Sndrs, FWD-ENV-T(env_of_t<Rcvr>), decayed-tuple, optional>...>
tuple<>
.
-5- The memberimpls-for<into_variant_t>::get-state
is initialized with a callable object equivalent to the following lambda:[]<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept -> type_identity<value_types_of_t<child-type<Sndr>, FWD-ENV-T(env_of_t<Rcvr>)>> { return {}; }
-3- Letsndr
andenv
be subexpressions such thatSndr
isdecltype((sndr))
andEnv
isdecltype((env))
. Ifsender-for<Sndr, stopped_as_optional_t>
isfalse
, or if the typesingle-sender-value-type<child-type<Sndr>, FWD-ENV-T(Env)>
is ill-formed orvoid
, then the expressionstopped_as_optional.transform_sender(sndr, env)
is ill-formed; otherwise, it is equivalent to:…auto&& [_, _, child] = sndr; using V = single-sender-value-type<child-type<Sndr>, FWD-ENV-T(Env)>;
as-sndr2(Sig)
in [exec.let] is incompleteSection: 33.9.12.8 [exec.let] Status: Ready Submitter: Eric Niebler Opened: 2025-02-03 Last modified: 2025-02-12
Priority: 1
View other active issues in [exec.let].
View all other issues in [exec.let].
Discussion:
33.9.12.8 [exec.let]/p9 reads:
Given a typeThe typeTag
and a packArgs
, letas-sndr2
be an alias template such thatas-sndr2<Tag(Args...)>
denotes the typecall-result-t<Fn, decay_t<Args>&...>
. Thenops2_variant_t
denotes the typeexcept with duplicate types removed.variant<monostate, connect_result_t<as-sndr2<LetSigs>, receiver2<Rcvr, Env>>...>
Env
is not specified. It should be env_t
from paragraph 7.
Paragraphs 8, 9, and 10 only make sense in relation to the lambda in paragraph 7, but that is not at all clear from the current wording. I suggest making paragraphs 8, 9, and 10 sub-bullets of paragraph 7.
[2025-02-07; Reflector poll]
Set priority to 1 after reflector poll.
[Hagenberg 2025-02-11; move to Ready]
Dropped the suggestion to nest p8-10 under p7.
Proposed resolution:
This wording is relative to N5001.
-7-
impls-for<decayed-typeof<let-cpo>>::get-state
is initialized with a callable object equivalent to the following:[]<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) requires see below { auto& [_, fn, child] = sndr; using fn_t = decay_t<decltype(fn)>; using env_t = decltype(let-env(child)); using args_variant_t = see below; using ops2_variant_t = see below; struct state-type { fn_t fn; // exposition only env_t env; // exposition only args_variant_t args; // exposition only ops2_variant_t ops2; // exposition only }; return state-type{std::forward_like<Sndr>(fn), let-env(child), {}, {}}; }
-8- Let
Sigs
be a pack of the arguments to thecompletion_signatures
specialization named bycompletion_signatures_of_t<child-type<Sndr>, env_of_t<Rcvr>>
. LetLetSigs
be a pack of those types inSigs
with a return type ofdecayed-typeof<set-cpo>
. Letas-tuple
be an alias template such thatas-tuple<Tag(Args...)>
denotes the typedecayed-tuple<Args...>
. Thenargs_variant_t
denotes the typevariant<monostate, as-tuple<LetSigs>...>
except with duplicate types removed.-9- Given a type
Tag
and a packArgs
, letas-sndr2
be an alias template such thatas-sndr2<Tag(Args...)>
denotes the typecall-result-t<Fn, decay_t<Args>&...>
. Thenops2_variant_t
denotes the typeexcept with duplicate types removed.variant<monostate, connect_result_t<as-sndr2<LetSigs>, receiver2<Rcvr,
Envenv_t>>...>-10- The requires-clause constraining the above lambda is satisfied if and only if the types
args_variant_t
andops2_variant_t
are well-formed.
let_[*].transform_env
is specified in terms of the let_*
sender itself instead of its childSection: 33.9.12.8 [exec.let] Status: Ready Submitter: Eric Niebler Opened: 2025-02-04 Last modified: 2025-02-12
Priority: 1
View other active issues in [exec.let].
View all other issues in [exec.let].
Discussion:
Imported from cplusplus/sender-receiver #319.
33.9.12.8 [exec.let] para 13 reads:
13. LetThe sender passed tosndr
andenv
be subexpressions, and letSndr
bedecltype((sndr))
. Ifsender-for<Sndr, decayed-typeof<let-cpo>>
isfalse
, then the expressionlet-cpo.transform_env(sndr, env)
is ill-formed. Otherwise, it is equal toJOIN-ENV(let-env(sndr), FWD-ENV(env))
.
let-env
here should be the child of sndr
.
[2025-02-07; Reflector poll]
Set priority to 1 after reflector poll.
"We seem to be missing a guarantee that auto [_,_,child] = sndr;
works.
We guarantee that it can be used in a structured binding, but not that it
must work with a size of three."
[Hagenberg 2025-02-11; move to Ready]
Proposed resolution:
This wording is relative to N5001.
-13- Letsndr
andenv
be subexpressions, and letSndr
bedecltype((sndr))
. Ifsender-for<Sndr, decayed-typeof<let-cpo>>
isfalse
, then the expressionlet-cpo.transform_env(sndr, env)
is ill-formed. Otherwise, it is equal toJOIN-ENV(let-env(sndr), FWD-ENV(env))
.auto& [_, _, child] = sndr; return JOIN-ENV(let-env(child), FWD-ENV(env));
connect(sndr, rcvr)
that rcvr
expression is only evaluated onceSection: 33.9.10 [exec.connect] Status: Ready Submitter: Eric Niebler Opened: 2025-02-07 Last modified: 2025-02-12
Priority: Not Prioritized
Discussion:
Imported from cplusplus/sender-receiver #325.
The current wording of connect(sndr, rcvr)
defines the new_sndr
expression as
transform_sender(decltype(get-domain-late(sndr, get_env(rcvr))){}, sndr, get_env(rcvr))
.
connect(sndr, rcvr)
as expression equivalent to new_sndr.connect(rcvr)
.
As currently worded, this requires evaluating the rcvr
expression twice. Note that the first
usage in the new_sndr
expression is unevaluated, but the second usage in get_env(rcvr)
is evaluated.
I think we need to add an extra sentence at the end of this section saying "Where the expression
rcvr
is only evaluated once." or similar.
[Hagenberg 2025-02-11; move to Ready]
Proposed resolution:
This wording is relative to N5001.
Modify 33.9.10 [exec.connect] as indicated:
-6- The expression
connect(sndr, rcvr)
is expression-equivalent to:
(6.1) —
Mandates: The type of the expression above satisfiesnew_sndr.connect(rcvr)
if that expression is well-formed.operation_state
.(6.2) — Otherwise,
connect-awaitable(new_sndr, rcvr)
.except that
Mandates:rcvr
is evaluated only once.sender<Sndr> && receiver<Rcvr>
istrue
.
default_domain::transform_env
should be returning FWD-ENV(env)
Section: 33.9.5 [exec.domain.default] Status: Ready Submitter: Eric Niebler Opened: 2025-02-07 Last modified: 2025-02-12
Priority: Not Prioritized
Discussion:
Imported from cplusplus/sender-receiver #168.
When writing a generic recursive sender transform, you need to ability to unpack an unknown sender
S
and recursively transform the children.
S
will use when connecting its
child senders, which is why transform_env
exists.
For an environment E
and a sender S
with tag T
child C
, the expression
default_domain().transform_env(S, E)
should return an environment E2
that is identical to the
environment of the receiver that S
uses to connect C
.
default_domain().transform_env(S, E)
will first check whether T().transform_env(S, E)
is
well-formed. If so, it will return that (e.g. when_all_t
has a transform_env
that adds a stop token
to the environment).
If T().transform_env(S, E)
is not well-formed, what should default_domain::transform_env
do? At
present, it returns E
unmodified.
But 33.9.12.1 [exec.adapt.general] has this:
[unless otherwise specified, when] a parent sender is connected to a receiver
rcvr
, any receiver used to connect a child sender has an associated environment equal toFWD-ENV(get_env(rcvr))
.
So the correct thing for default_domain::transform_env
to do is to return FWD-ENV(get_env(rcvr))
.
[Hagenberg 2025-02-11; move to Ready]
Proposed resolution:
This wording is relative to N5001.
Modify 33.9.5 [exec.domain.default] as indicated:
template<sender Sndr, queryable Env> constexpr queryable decltype(auto) transform_env(Sndr&& sndr, Env&& env) noexcept;-5- Let
e
be the expressiontag_of_t<Sndr>().transform_env(std::forward<Sndr>(sndr), std::forward<Env>(env))if that expression is well-formed; otherwise,
-6- Mandates:.
static_cast<Env>FWD-ENV(std::forward<Env>(env))noexcept(e)
istrue
. -7- Returns:e
.
ostream::sentry
destructor should handle exceptionsSection: 31.7.6.2.4 [ostream.sentry] Status: Tentatively Ready Submitter: Jonathan Wakely Opened: 2025-01-14 Last modified: 2025-02-07
Priority: Not Prioritized
View other active issues in [ostream.sentry].
View all other issues in [ostream.sentry].
Discussion:
LWG 397(i) suggested changing 31.7.6.2.4 [ostream.sentry] to
say that the ostream::sentry
destructor doesn't throw any exceptions.
That issue was closed as resolved by LWG 835(i) which included
the "Throws: Nothing" change to the sentry
destructor.
However, that part of the resolution never seems to have been applied to
the working draft. N3091 mentions applying LWG 835 for
N3090 but the destructor change is missing, maybe because
the paragraph for the sentry destructor had been renumbered from p17 to p4
and LWG 835 didn't show sufficient context to indicate the intended location.
The problem described in LWG 397(i) is still present:
the streambuf operations can fail, and the sentry needs to handle that.
The changes for LWG 835(i) ensure no exception is thrown if
rdbuf()->pubsync()
returns -1 on failure, but do nothing for
the case where it throws an exception (the original topic of LWG 397!).
Because C++11 made ~sentry
implicitly noexcept
,
an exception from rdbuf()->pubsync()
will terminate the process.
That needs to be fixed.
Libstdc++ does terminate if pubsync()
throws when called by ~sentry
.
Both MSVC and Libc++ silently swallow exceptions.
It seems preferable to handle the exception and report an error,
just as we do when pubsync()
returns -1.
[2025-02-07; Reflector poll]
Set status to Tentatively Ready after six votes in favour during reflector poll.
Proposed resolution:
This wording is relative to N5001.
Modify 31.7.6.2.4 [ostream.sentry] as indicated:
~sentry();
-4- If(os.flags() & ios_base::unitbuf) && !uncaught_exceptions() && os.good()
istrue
, callsos.rdbuf()->pubsync()
. If that function returns −1 or exits via an exception, setsbadbit
inos.rdstate()
without propagating an exception.
operation_state
concept can be simplifiedSection: 33.8.1 [exec.opstate.general] Status: Tentatively Ready Submitter: Eric Niebler Opened: 2025-02-03 Last modified: 2025-02-07
Priority: Not Prioritized
Discussion:
Imported from cplusplus/sender-receiver #312.
The current defn of the operation_state
concept is:
template<class O>
concept operation_state =
derived_from<typename O::operation_state_concept, operation_state_t> &&
is_object_v<O> &&
requires (O& o) {
{ start(o) } noexcept;
};
I think the is_object_v<O>
constraint is not needed
because the derived_from
constraint has already established that
O
is a class type.
And start(o)
is always noexcept
now that start
mandates the
noexcept
-ness of op.start()
.
[2025-02-07; Reflector poll]
Set status to Tentatively Ready after seven votes in favour during reflector poll.
Proposed resolution:
This wording is relative to N5001.
template<class O> concept operation_state = derived_from<typename O::operation_state_concept, operation_state_t> &&
is_object_v<O> &&requires (O& o) {{start(o)} noexcept; };
with-await-transform::await_transform
should not use a deduced return typeSection: 33.9.4 [exec.awaitable] Status: Tentatively Ready Submitter: Brian Bi Opened: 2025-02-03 Last modified: 2025-02-07
Priority: Not Prioritized
Discussion:
Imported from cplusplus/sender-receiver #309.
33.9.4 [exec.awaitable]/p5
The use of the deduced return type causes the definition of the sender's
as_awaitable
method to be instantiated too early,
e.g., when the sender is passed to get_completion_signatures
.
[Eric provides wording]
[2025-02-07; Reflector poll]
Set status to Tentatively Ready after five votes in favour during reflector poll.
Proposed resolution:
This wording is relative to N5001.
-5- Letwith-await-transform
be the exposition-only class template:namespace std::execution { template<class T, class Promise> concept has-as-awaitable = // exposition only requires (T&& t, Promise& p) { { std::forward<T>(t).as_awaitable(p) } -> is-awaitable<Promise&>; }; template<class Derived> struct with-await-transform { // exposition only template<class T> T&& await_transform(T&& value) noexcept { return std::forward<T>(value); } template<has-as-awaitable<Derived> T>
decltype(auto)auto await_transform(T&& value) noexcept(noexcept(std::forward<T>(value).as_awaitable(declval<Derived&>()))) -> decltype(std::forward<T>(value).as_awaitable(declval<Derived&>())) { return std::forward<T>(value).as_awaitable(static_cast<Derived&>(*this)); } }; }
mdspan
layout mapping requirements for rank == 0
Section: 23.7.3.4.2 [mdspan.layout.reqmts] Status: Tentatively Ready Submitter: Mark Hoemmen Opened: 2025-03-03 Last modified: 2025-03-09
Priority: Not Prioritized
Discussion:
23.7.3.4.2 [mdspan.layout.reqmts] p19-21 says that a layout mapping needs to
provide m.stride(r)
. However, 23.7.3.4.5.3 [mdspan.layout.left.obs] p5 constrains
layout_left::mapping<Extents>::stride(r)
on Extents::rank() > 0
being true
. The same is true of layout_right::mapping
(23.7.3.4.6.3 [mdspan.layout.right.obs] p5). (The other Standard mappings in
23.7.3 [views.multidim] and 29.9 [linalg] do not have this constraint.)
This suggests that a rank-zero layout_{left,right}::mapping
does not
conform with the layout mapping requirements.
r
must be in the range [0, rank()
) for the layout mapping's
extents type. If such an r
does not exist, which is the case for a
rank-zero layout mapping, then the m.stride(r)
requirement is
vacuous. This implies that a rank-zero layout_{left,right}::mapping
fully conforms with the layout mapping requirements.
It is definitely the design intent for rank-zero mdspan
to work, and
for it to represent a view of a single element. Users can create
rank-zero mdspan
by invoking its constructor, or by using
submdspan
where all the slice arguments are convertible to
index_type
. Even though the normative wording permits this, adding
a Note would clarify the design intent without making the wording
redundant. This was the preferred change per LWG reflector
discussion.
[2025-06-13; Reflector poll]
Set status to Tentatively Ready after five votes in favour during reflector poll.
Proposed resolution:
This wording is relative to N5001.
Modify 23.7.3.4.2 [mdspan.layout.reqmts] as indicated:
m.stride(r)-19- Preconditions:
-20- Result:m.is_strided()
istrue
.typename M::index_type
-21- Returns:sr
as defined inm.is_strided()
above. [Note ?: It is not required form.stride(r)
to be well-formed ifm.extents().rank()
is zero, even ifm.is_always_strided()
istrue
. — end note]
expected
constructor from a single value missing a constraintSection: 22.8.6.2 [expected.object.cons] Status: Tentatively Ready Submitter: Bronek Kozicki Opened: 2025-03-12 Last modified: 2025-03-15
Priority: Not Prioritized
View all other issues in [expected.object.cons].
Discussion:
When an expected
object is initialized with a constructor taking first parameter of type unexpect_t
,
the expectation is that the object will be always initialized in disengaged state (i.e. the user expected
postcondition is that has_value()
will be false
), as in the example:
struct T { explicit T(auto) {} }; struct E { E() {} }; int main() { expected<T, E> a(unexpect); assert(!a.has_value()); }
This does not hold when both value type T
and error type E
have certain properties. Observe:
struct T { explicit T(auto) {} }; struct E { E(int) {} }; // Only this line changed from the above example int main() { expected<T, E> a(unexpect); assert(!a.has_value()); // This assert will now fail }
In the example above the overload resolution of a
finds the universal single parameter constructor for
initializing expected
in engaged state (22.8.6.2 [expected.object.cons] p23):
template<class U = remove_cv_t<T>> constexpr explicit(!is_convertible_v<U, T>) expected(U&& v);
This constructor has a list of constraints which does not mention unexpect_t
(but it mentions e.g. unexpected
and
in_place_t
). Email exchange with the author of expected
confirmed that it is an omission.
is_same_v<remove_cvref_t<U>, unexpect_t>
isfalse
This will result in the above, most likely buggy, program to become ill-formed. If the user intent was for the object
to be constructed in an engaged state, passing unexpect_t
to the T
constructor, they can fix the compilation error
like so:
expected<T, E> a(in_place, unexpect);
[2025-06-13; Reflector poll]
Set status to Tentatively Ready after nine votes in favour during reflector poll.
Proposed resolution:
This wording is relative to N5001.
Modify 22.8.6.2 [expected.object.cons] as indicated:
template<class U = remove_cv_t<T>> constexpr explicit(!is_convertible_v<U, T>) expected(U&& v);-23- Constraints:
(23.1) —
is_same_v<remove_cvref_t<U>, in_place_t>
isfalse
; and(23.2) —
is_same_v<expected, remove_cvref_t<U>>
isfalse
; and(23.?) —
is_same_v<remove_cvref_t<U>, unexpect_t>
isfalse
; and(23.3) —
remove_cvref_t<U>
is not a specialization ofunexpected
; and(23.4) —
is_constructible_v<T, U>
istrue
; and(23.5) — if
T
is cvbool
,remove_cvref_t<U>
is not a specialization ofexpected
.-24- Effects: Direct-non-list-initializes
-25- Postconditions:val
withstd::forward<U>(v)
.has_value()
istrue
. -26- Throws: Any exception thrown by the initialization ofval
.
Section: 29.5.4.5 [rand.eng.philox] Status: Tentatively Ready Submitter: Jiang An Opened: 2025-03-15 Last modified: 2025-03-15
Priority: Not Prioritized
View other active issues in [rand.eng.philox].
View all other issues in [rand.eng.philox].
Discussion:
Philox engines don't seem to require floating-point operations or support from the operating system, so they are probably suitable for freestanding. However, as P2976R1 was finished before the adoption of P2075R6, these engines are not made freestanding yet.
[2025-06-13; Reflector poll]
Set status to Tentatively Ready after ten votes in favour during reflector poll.
Proposed resolution:
This wording is relative to N5001.
Modify 29.5.2 [rand.synopsis], header <random>
synopsis, as indicated:
[…] // 29.5.4.5 [rand.eng.philox], class template philox_engine template<class UIntType, size_t w, size_t n, size_t r, UIntType... consts> class philox_engine; // partially freestanding […] using philox4x32 = see below; // freestanding using philox4x64 = see below; // freestanding […]
Modify 29.5.4.5 [rand.eng.philox], class template philox_engine
synopsis, as indicated:
namespace std { template<class UIntType, size_t w, size_t n, size_t r, UIntType... consts> class philox_engine { […] // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const philox_engine& x); // hosted template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, philox_engine& x); // hosted }; }
noexcept
operator in [exec.when.all]Section: 33.9.12.11 [exec.when.all] Status: Tentatively Ready Submitter: Ian Petersen Opened: 2025-03-17 Last modified: 2025-03-22
Priority: Not Prioritized
Discussion:
In 33.9.12.11 [exec.when.all] p7, the impls-for<when_all_t>::get-state
member is defined to be equivalent to the following lambda:
[]<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept(e) -> decltype(e) { return e; }
and e
is later defined to be:
std::forward<Sndr>(sndr).apply(make-state<Rcvr>())
Together, the two definitions imply that the noexcept
clause on the provided lambda is:
noexcept(std::forward<Sndr>(sndr).apply(make-state<Rcvr>()))
which is invalid.
Presumably, the lambda should be defined like so (with an extranoexcept
operator in the noexcept
clause):
[]<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept(noexcept(e)) -> decltype(e) { return e; }
[2025-06-13; Reflector poll]
Set status to Tentatively Ready after seven votes in favour during reflector poll.
Proposed resolution:
This wording is relative to N5008.
Modify 33.9.12.11 [exec.when.all] as indicated:
-7- The member
impls-for<when_all_t>::get-state
is initialized with a callable object equivalent to the following lambda expression:[]<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept(noexcept(e)) -> decltype(e) { return e; }
datapar::chunk<N>
should use simd-size-type
instead of size_t
Section: 29.10.3 [simd.syn], 29.10.7.8 [simd.creation] Status: Tentatively Ready Submitter: Matthias Kretz Opened: 2025-03-22 Last modified: 2025-03-22
Priority: Not Prioritized
Discussion:
All index values and simd widths in subclause "Data-parallel types" use the
type simd-size-type
. Specifically, the NTTP of std::datapar::resize
uses simd-size-type
and std::datapar::chunk
is "implemented"
using std::datapar::resize
.
chunk<N>
, N
is of type size_t
and needs to be
converted to simd-size-type
in the effects clause where it is
passed to resize. The NTTP of chunk should use simd-size-type
instead of size_t
.
[2025-06-13; Reflector poll]
Set status to Tentatively Ready after seven votes in favour during reflector poll.
Proposed resolution:
This wording is relative to N5008.
Modify 29.10.3 [simd.syn], header <simd>
synopsis, as indicated:
namespace std::datapar { […] template<simd-size-typesize_tN, class T, class Abi> constexpr auto chunk(const basic_simd<T, Abi>& x) noexcept; template<simd-size-typesize_tN, size_t Bytes, class Abi> constexpr auto chunk(const basic_simd_mask<Bytes, Abi>& x) noexcept; […] }
Modify 29.10.7.8 [simd.creation] as indicated:
template<simd-size-typesize_tN, class T, class Abi> constexpr auto chunk(const basic_simd<T, Abi>& x) noexcept;-4- Effects: Equivalent to:
return chunk<resize_t<N, basic_simd<T, Abi>>>(x);
template<simd-size-typesize_tN, size_t Bytes, class Abi> constexpr auto chunk(const basic_simd_mask<Bytes, Abi>& x) noexcept;-5- Effects: Equivalent to:
return chunk<resize_t<N, basic_simd_mask<Bytes, Abi>>>(x);
datapar::resize
does not resizeSection: 29.10.4 [simd.traits] Status: Tentatively Ready Submitter: Tim Song Opened: 2025-03-24 Last modified: 2025-06-12
Priority: Not Prioritized
Discussion:
The wording actually requires the size to be left unchanged.
[2025-06-12; Reflector poll]
Set status to Tentatively Ready after seven votes in favour during reflector poll.
Proposed resolution:
This wording is relative to N5008.
Modify 29.10.4 [simd.traits] as indicated:
template<simd-size-type N, class V> struct resize { using type = see below; };[…]
-9- IfV
is a specialization ofbasic_simd
, letAbi1
denote an ABI tag such thatbasic_simd<T, Abi1>::size()
equals. If
V::size()NV
is a specialization ofbasic_simd_mask
, letAbi1
denote an ABI tag such thatbasic_simd_mask<sizeof(T), Abi1>::size()
equals.
V::size()N
std::erase
for hive
should specify return type as
bool
Section: 23.3.9.6 [hive.erasure] Status: Tentatively Ready Submitter: Hewill Kang Opened: 2025-03-24 Last modified: 2025-06-12
Priority: Not Prioritized
Discussion:
This is a follow up to LWG 4135(i), which incidentally adds a default template
parameter for U
to be consistent with other erase
functions,
which is editorial since the declaration already has it.
[2025-06-12; Reflector poll]
Set status to Tentatively Ready after seven votes in favour during reflector poll.
Proposed resolution:
This wording is relative to N5008.
Modify 23.3.9.6 [hive.erasure] as indicated:
template<class T, class Allocator, class U = T> typename hive<T, Allocator>::size_type erase(hive<T, Allocator>& c, const U& value);-1- Effects: Equivalent to:
return erase_if(c, [&](const auto& elem) -> bool { return elem == value; });
<hive>
doesn't provide std::begin/end
Section: 24.7 [iterator.range] Status: Tentatively Ready Submitter: Hewill Kang Opened: 2025-03-25 Last modified: 2025-06-12
Priority: Not Prioritized
View other active issues in [iterator.range].
View all other issues in [iterator.range].
Discussion:
24.7 [iterator.range] should add <hive>
to the list as the latter provides
a series of range access member functions such as begin/end
.
[2025-06-12; Reflector poll]
Set status to Tentatively Ready after six votes in favour during reflector poll.
Proposed resolution:
This wording is relative to N5008.
Modify 24.7 [iterator.range] as indicated:
-1- In addition to being available via inclusion of the
<iterator>
header, the function templates in 24.7 [iterator.range] are available when any of the following headers are included:<array>
,<deque>
,<flat_map>
,<flat_set>
,<forward_list>
,<hive>
,<inplace_vector>
,<list>
,<map>
,<regex>
,<set>
,<span>
,<string>
,<string_view>
,<unordered_map>
,<unordered_set>
, and<vector>
.
cache_latest_view
and to_input_view
miss reserve_hint
Section: 25.7.34.2 [range.cache.latest.view], 25.7.35.2 [range.to.input.view] Status: Tentatively Ready Submitter: Hewill Kang Opened: 2025-03-25 Last modified: 2025-06-12
Priority: 2
Discussion:
Intuitively, both view classes should also have reserve_hint
members.
[2025-06-12; Reflector poll]
Set priority to 2 after reflector poll.
[2025-06-13; Reflector poll]
Set status to Tentatively Ready after five votes in favour during reflector poll.
Proposed resolution:
This wording is relative to N5008.
Modify 25.7.34.2 [range.cache.latest.view] as indicated:
[…]namespace std::ranges { template<input_range V> requires view<V> class cache_latest_view : public view_interface<cache_latest_view<V>> { […] constexpr auto size() requires sized_range<V>; constexpr auto size() const requires sized_range<const V>; constexpr auto reserve_hint() requires approximately_sized_range<V>; constexpr auto reserve_hint() const requires approximately_sized_range<const V>; }; […] }constexpr auto size() requires sized_range<V>; constexpr auto size() const requires sized_range<const V>;-4- Effects: Equivalent to:
return ranges::size(base_);
constexpr auto reserve_hint() requires approximately_sized_range<V>; constexpr auto reserve_hint() const requires approximately_sized_range<const V>;-?- Effects: Equivalent to:
return ranges::reserve_hint(base_);
Modify 25.7.35.2 [range.to.input.view] as indicated:
[…]template<input_range V> requires view<V> class to_input_view : public view_interface<to_input_view<V>> { […] constexpr auto size() requires sized_range<V>; constexpr auto size() const requires sized_range<const V>; constexpr auto reserve_hint() requires approximately_sized_range<V>; constexpr auto reserve_hint() const requires approximately_sized_range<const V>; }; […]constexpr auto size() requires sized_range<V>; constexpr auto size() const requires sized_range<const V>;-5- Effects: Equivalent to:
return ranges::size(base_);
constexpr auto reserve_hint() requires approximately_sized_range<V>; constexpr auto reserve_hint() const requires approximately_sized_range<const V>;-?- Effects: Equivalent to:
return ranges::reserve_hint(base_);
chunk_view::outer-iterator::value_type
should provide reserve_hint
Section: 25.7.29.4 [range.chunk.outer.value] Status: Tentatively Ready Submitter: Hewill Kang Opened: 2025-03-26 Last modified: 2025-06-12
Priority: Not Prioritized
View other active issues in [range.chunk.outer.value].
View all other issues in [range.chunk.outer.value].
Discussion:
Consider:
views::istream<int>(is) | views::chunk(N) | ranges::to<std::list<std::vector<int>>>();
When the stream is large enough, each chunk will be of size N
in most cases, except it is the
last chunk.
In this case, there is no reason not to provide a reserve_hint
as this can be easily done by just
return remainder_
. Otherwise, when N
is large, each vector will be reallocated
multiple times unnecessarily.
This is also consistent with the forward_range
version, since its value type is
views::take(subrange(current_, end_), n_)
, which always has a
reserve_hint
as take_view
unconditionally provides it.
[2025-06-12; Reflector poll]
Set status to Tentatively Ready after five votes in favour during reflector poll.
Proposed resolution:
This wording is relative to N5008.
Modify 25.7.29.4 [range.chunk.outer.value] as indicated:
[…]namespace std::ranges { template<view V> requires input_range<V> struct chunk_view<V>::outer-iterator::value_type : view_interface<value_type> { […] constexpr auto size() const requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>; constexpr auto reserve_hint() const noexcept; }; }constexpr auto size() const requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;-4- Effects: Equivalent to:
return to-unsigned-like(ranges::min(parent_->remainder_, ranges::end(parent_->base_) - *parent_->current_));constexpr auto reserve_hint() const noexcept;-?- Effects: Equivalent to:
return to-unsigned-like(parent_->remainder_);
flat_map
's transparent comparator no longer works for string literalsSection: 23.6.8.7 [flat.map.modifiers] Status: New Submitter: Hui Xie Opened: 2025-03-29 Last modified: 2025-03-29
Priority: Not Prioritized
View other active issues in [flat.map.modifiers].
View all other issues in [flat.map.modifiers].
Discussion:
According to the spec, the following code should hard error
std::flat_map<std::string, int, std::less<>> m;
m.try_emplace("abc", 5); // hard error
The reason is that we specify in 23.6.8.7 [flat.map.modifiers] p21 the effect to be
as if ranges::upper_bound
is called.
ranges::upper_bound
requires indirect_strict_weak_order
, which requires the comparator to be
invocable for all combinations. In this case, it requires
const char (&)[4] < const char (&)[4]
to be well-formed, which is no longer the case in C++26 after P2865R6.
We should just usestd::upper_bound
instead. libstdc++ already uses std::upper_bound
.
libc++ uses ranges::upper_bound
but clang has not yet implemented P2865
properly.
Proposed resolution:
This wording is relative to N5008.
Modify 23.6.8.7 [flat.map.modifiers] as indicated:
template<class K, class... Args> constexpr pair<iterator, bool> try_emplace(K&& k, Args&&... args); template<class K, class... Args> constexpr iterator try_emplace(const_iterator hint, K&& k, Args&&... args);-19- Constraints: […]
-20- Preconditions: […] -21- Effects: If the map already contains an element whose key is equivalent tok
,*this
andargs...
are unchanged. Otherwise equivalent to:auto key_it = upper_bound(c.keys.begin(), c.keys.end(), k, compare)ranges::upper_bound(c.keys, k, compare); auto value_it = c.values.begin() + distance(c.keys.begin(), key_it); c.keys.emplace(key_it, std::forward<K>(k)); c.values.emplace(value_it, std::forward<Args>(args)...);
ranges::distance
does not work with volatile iteratorsSection: 24.4.4.3 [range.iter.op.distance] Status: Tentatively Ready Submitter: Hewill Kang Opened: 2025-04-12 Last modified: 2025-06-12
Priority: Not Prioritized
View all other issues in [range.iter.op.distance].
Discussion:
After LWG 3664(i), ranges::distance
computes the distance between last
and first
by returning last - static_cast<const decay_t<I>&>(first)
when the
two are subtractable. However, this will cause a hard error if first
is volatile-qualified
(demo):
#include <iterator>
int main() {
int arr[] = {1, 2, 3};
int* volatile ptr = arr;
// return std::distance(ptr, arr + 3); // this is ok
return std::ranges::distance(ptr, arr + 3); // hard error
}
The resolution changes the Effects of LWG 3664(i) from "cute" to "noncute".
[2025-06-12; Reflector poll]
Set status to Tentatively Ready after eight votes in favour during reflector poll.
"Would prefer auto(first)
but the current wording is correct."
Proposed resolution:
This wording is relative to N5008.
Modify 24.4.4.3 [range.iter.op.distance] as indicated:
template<class I, sized_sentinel_for<decay_t<I>> S> constexpr iter_difference_t<decay_t<I>> ranges::distance(I&& first, S last);-3- Effects: Equivalent to:
if constexpr (!is_array_v<remove_reference_t<I>>) return last - first; else return last - static_cast<constdecay_t<I>&>(first);
counted_iterator
and default_sentinel_t
should be noexcept
Section: 24.5.7.1 [counted.iterator], 24.5.7.5 [counted.iter.nav], 24.5.7.6 [counted.iter.cmp] Status: Tentatively Ready Submitter: Hewill Kang Opened: 2025-04-18 Last modified: 2025-06-12
Priority: Not Prioritized
View all other issues in [counted.iterator].
Discussion:
counted_iterator
can be compared or subtracted from default_sentinel_t
,
which only involves simple integer arithmetic and does not have any Preconditions.
noexcept
.
[2025-06-12; Reflector poll]
Set status to Tentatively Ready after seven votes in favour during reflector poll.
Proposed resolution:
This wording is relative to N5008.
Modify 24.5.7.1 [counted.iterator] as indicated:
namespace std { template<input_or_output_iterator I> class counted_iterator { public: […] friend constexpr iter_difference_t<I> operator-( const counted_iterator& x, default_sentinel_t) noexcept; friend constexpr iter_difference_t<I> operator-( default_sentinel_t, const counted_iterator& y) noexcept; […] friend constexpr bool operator==( const counted_iterator& x, default_sentinel_t) noexcept; […] }; […] }
Modify 24.5.7.5 [counted.iter.nav] as indicated:
friend constexpr iter_difference_t<I> operator-( const counted_iterator& x, default_sentinel_t) noexcept;-15- Effects: Equivalent to:
return -x.length;
friend constexpr iter_difference_t<I> operator-( default_sentinel_t, const counted_iterator& y) noexcept;-16- Effects: Equivalent to:
return y.length;
Modify 24.5.7.6 [counted.iter.cmp] as indicated:
friend constexpr bool operator==( const counted_iterator& x, default_sentinel_t) noexcept;-3- Effects: Equivalent to:
return x.length == 0;
<stdbit.h>
is not yet freestandingSection: 22.12 [stdbit.h.syn] Status: Tentatively Ready Submitter: Jiang An Opened: 2025-04-24 Last modified: 2025-06-12
Priority: Not Prioritized
Discussion:
Per C23/WG14 N3220 4 p7, <stdbit.h>
is freestanding in C23, but C++ hasn't required it for a freestanding implementation.
LWG 4049(i) is related but doesn't cover this, because there's no <cstdbit>
standard header.
[2025-06-12; Reflector poll]
Set status to Tentatively Ready after six votes in favour during reflector poll.
Proposed resolution:
This wording is relative to N5008.
Modify Table 27 [tab:headers.cpp.fs] as indicated:
Table 27: C++ headers for freestanding implementations [tab:headers.cpp.fs] Subclause Header […]
22.11 [bit] Bit manipulation <bit>
22.12 [stdbit.h.syn] C-compatible bit manipulation <stdbit.h>
23.3.3 [array] Class template array
<array>
[…]
Modify 22.12 [stdbit.h.syn], header <stdbit.h>
synopsis, as indicated:
// all freestanding #define __STDC_VERSION_STDBIT_H__ 202311L #define __STDC_ENDIAN_BIG__ see below #define __STDC_ENDIAN_LITTLE__ see below #define __STDC_ENDIAN_NATIVE__ see below […]