volatile
-qualified perfect forwarding call wrapperSection: 22.10.4 [func.require] Status: New Submitter: Jiang An Opened: 2023-11-05 Last modified: 2024-03-11
Priority: 3
View all other issues in [func.require].
View all issues with New status.
Discussion:
22.10.4 [func.require]/4 says:
[…] This forwarding step delivers a state entity of type
T
as cvT&
when the call is performed on an lvalue of the call wrapper type and as cvT&&
otherwise, where cv represents the cv-qualifiers of the call wrapper and where cv shall be neithervolatile
norconst volatile
.
The "shall" seemingly indicates a requirement for user codes that calling a volatile perfect forwarding call wrapper is undefined behavior. Such requirement seems to be combined with requirements for implementations in an unusual way.
Moreover, it is unclear whether UB is intended here. Perhaps we only want calling such avolatile
wrapper to be conditionally-supported. E.g. when the operator()
happens to be implementable as a
static member function, calling a volatile
wrapper can be naturally supported and have expected
behavior.
[2024-03-11; Reflector poll]
Set priority to 3 after reflector poll.
LWG 2487 doesn't seem to intend to forbid volatile
support as a conforming extension.
P1065R2 made it ill-formed for std::bind
but didn't
make the same change to the definition of perfect forwarding call wrapper.
So given an as_volatile
function that works like std::as_const
,
as_volatile(std::bind(&T::fn))(t)
is ill-formed but
as_volatile(std::mem_fn(&T::fn))(t)
is undefined.
Supporting it as a conforming extension is fine, but making it UB is not.
Maybe "conditionally supported" instead?
Proposed resolution:
This wording is relative to N4964.
Modify 22.10.4 [func.require] as indicated:
4 A perfect forwarding call wrapper is an argument forwarding call wrapper that forwards its state entities to the underlying call expression. This forwarding step delivers a state entity of type
T
as cvT&
when the call is performed on an lvalue of the call wrapper type and as cvT&&
otherwise, where cv represents the cv-qualifiers of the call wrapperand where cv shall be neither, except that if cv is eithervolatile
norconst volatile
volatile
orconst volatile
, it is unspecified whether the call is well-formed.