P1169R4 static operator()
#4053
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #2954.
This updates the STL's CTAD for
std::functionandpackaged_taskto work with a C++23 Core Language feature that was implemented in Clang 16 (which we began requiring in VS 2022 17.7). It will automatically "light up" when MSVC and EDG claim support by defining the feature-test macro.<functional>_Deduce_signatureperforms SFINAE for&_Fx::operator(), which needs to be well-formed for both the old and new cases. Then, we send_Fx(because the new path will need it) anddecltype(&_Fx::operator())(so both paths don't need to recompute it) up to the layer_Deduce_from_call_operator._Deduce_from_call_operatoris chosen, and we use the_Is_memfunptrmachinery exactly as before. (I updated the WP citation, but the paragraph number is the same.)#ifdef __cpp_static_call_operatorisn't commented as TRANSITION, because Clang backported it unconditionally (thanks @frederick-vs-ja).staticseparately from inspecting its type (see note here). I'm using the technique mentioned in the paper, detecting whether we can formf.operator(). Note that the value category doesn't matter, so I'm just passing_Fxtodeclval.this", which we previously implemented, also produces a plain function pointer (instead of a PMF), but for that we need to drop the "self" parameter. All that happens in the old_Is_memfunptrpath.static, we don't take the old_Is_memfunptrpath. Instead we use the new_Inspect_static_call_operatorpath, with a citation for the relevant paragraph. This path is dedicated, instead of intertwined with other<functional>logic, so we don't need to bother with a_Guide_typeand_Identityetc., we'll just directly have atypeat the end, which is what_Deduce_signatureultimately needs to provide.noexceptis part of the type, we're required to ignore it. (As usual this is guarded by__cpp_noexcept_function_typebecause the compiler has an escape hatch that is permanently supported.)<yvals_core.h>_HAS_CXX23section, at least until we get clarity on whether MSVC and EDG will backport.Tests
staticoperator is inherited from a base class. I also test what happens if thestaticoperator is markednoexcept; regardless of whether it's part of the type system (usual_latest_matrix.lstprovides that coverage), we deduce the same signature. Everything is tested for bothstd::functionandpackaged_task.staticcall operator to keep the compiler honest. We need to work around LLVM-62594 (thanks @cpplearner), indicating that this coverage was a good idea! 😸