-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
static operator()
for stateless functors
#4358
static operator()
for stateless functors
#4358
Conversation
Co-authored-by: Casey Carter <[email protected]>
Drive-by and fixes: change `(*this)(...)` to `operator()(...)`, and use more internal static member functions.
Note: `_Synth_three_way::operator()` is specified to be non-static in [expos.only.entity], but the class itself is exposition-only, so I think it's fine to make it `static`. Drive-by: `_Cmp_cs::operator()` lacked `const` befor. IMO it should have `const` when `static` is unavailable.
Not a copy-paste mistake: `is_nothrow_default_constructible_v<_Ty>` is correct for both `_Inplace_default_construct_fn` and `_Inplace_value_construct_fn`.
…` to be `consteval` functions.
…_STATIC_CALL_OPERATOR constexpr`
@@ -2024,5 +2026,13 @@ compiler option, or define _ALLOW_RTCc_IN_STL to suppress this error. | |||
#define _STL_INTERNAL_STATIC_ASSERT(...) | |||
#endif // ^^^ !defined(_ENABLE_STL_INTERNAL_CHECK) ^^^ | |||
|
|||
#ifdef __cpp_static_call_operator |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No change requested: This "light up" code will result in warnings being emitted as soon as MSVC implements this feature and defines the macro. However, I think that's ok - we live in the MSVC compiler front-end devs' branch prod/fe
, and they can patch our headers while checking in the feature (and we can use the macro to deal with the temporary difference between MSVC-internal and VS Preview).
This is similar to the "assert bug" pattern which I dislike so much (any code in the STL that breaks when compilers start doing the right thing), but having it happen on one rare and expected occasion is fine, and the MSVC FE lives much "closer" to us than EDG (blocking EDG code insertions is much more obnoxious for logistical reasons).
@@ -210,7 +210,7 @@ struct _Lex_compare_memcmp_classify_pred<_Elem, _Elem, _Char_traits_lt<char_trai | |||
template <class _RxTraits> | |||
struct _Cmp_cs { // functor to compare two character values for equality | |||
using _Elem = typename _RxTraits::char_type; | |||
bool operator()(_Elem _Ex1, _Elem _Ex2) { | |||
_STATIC_CALL_OPERATOR bool operator()(_Elem _Ex1, _Elem _Ex2) _CONST_CALL_OPERATOR { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No change requested: Great catch for the missing const
here! 😻
Thanks for this surprisingly large PR - I always forgot how big the STL has grown! 😹 I pushed a few changes, including a couple of refactorings - please double-check. I've also relabeled this as a (minor) performance improvement. |
I'm mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed. |
Thanks for powering the STL with |
Fixes #4130. This PR makes the
operator()
s of stateless functorsstatic
, including those of captureless lambdas, except for...operator()
s that are intentionally notconst
to me (e.g._Rand_urng_from_func::operator()
),operator()
s that explicitly specifiedconst
and non-static
in the standard wording (except for that ofsynth-three-way
where the functor itself is exposition-only),basic_format_arg::handle
, because there seems a bug of Clang 17 involving calling conventions for static lambdas, which seems fixed in Clang 18.List of explicitly
const
and non-static
functors in the standard library<memory>
:std::default_delete
std::owner_less
std::owner_hash
std::owner_equal
<type_traits>
:std::integral_constant
<chrono>
:std::chrono::clock_time_conversion
<functional>
:std::plus
std::minus
std::multiplies
std::divides
std::modulus
std::negate
std::equal_to
std::not_equal_to
std::greater
std::less
std::greater_equal
std::less_equal
std::compare_three_way
std::ranges::equal_to
std::ranges::not_equal_to
std::ranges::greater
std::ranges::less
std::ranges::greater_equal
std::ranges::less_equal
std::logical_and
std::logical_or
std::logical_not
std::bit_and
std::bit_or
std::bit_xor
std::bit_not
std::identity
Drive-by changes:
(*this)(...)
tooperator()(...)
wheneveroperator()
is possiblystatic
.ranges::swap
needs some special handling.static
._Cmp_cs::operator()
conditionallyconst
orstatic
- it seems unintended to me that it wasn'tconst
.