Deducing this for delegates#1553
Conversation
|
I found that when running the CI on my own fork, Clang 20 target x86 generated incorrect code, causing the test to fail. The characteristic of this bug is that in the constructor of observed_sender at L101, |
There was a problem hiding this comment.
Pull request overview
This PR fixes a C++23 “deducing this” compatibility issue for C++/WinRT delegates by ensuring the upcall invokes the underlying handler type (lambda) rather than the non-copyable delegate wrapper type. It also adds a dedicated C++23 test target to validate the behavior in CI and local builds.
Changes:
- Update delegate invocation codegen/runtime to call
operator()viastatic_cast<H&>(*this)sothis autodeduces as the handler type. - Add a new
test_cpp23test project (MSBuild + CMake) and wire it into scripts/CI. - Adjust Catch2 UDL declarations to the standard-conforming
operator ""_suffixspelling (needed for newer language modes).
Reviewed changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
cppwinrt/code_writers.h |
Changes generated delegate Invoke upcall to use static_cast<H&>(*this) for correct this auto deduction. |
strings/base_delegate.h |
Updates runtime delegate invoke path to call through the handler subobject (H) rather than the wrapper. |
test/test_cpp23/delegate_deducing_this.cpp |
Adds C++23 tests covering delegates/handlers using explicit object parameters (this auto). |
test/test_cpp23/main.cpp |
New Catch2 test runner for the C++23 test target. |
test/test_cpp23/pch.h |
New PCH header for the C++23 test target. |
test/test_cpp23/pch.cpp |
New PCH source for the C++23 test target. |
test/test_cpp23/CMakeLists.txt |
Adds CMake build definition for test_cpp23. |
test/test_cpp23/test_cpp23.vcxproj |
Adds MSBuild project for test_cpp23 targeting latest C++ mode / C++23 projection setting. |
test/CMakeLists.txt |
Wires test_cpp23 into the test CMake build. |
test/catch.hpp |
Fixes user-defined literal operator spelling to standard ""_suffix form. |
.github/workflows/ci.yml |
Adds test_cpp23 to the Windows test matrix. |
cppwinrt.sln |
Adds the new test_cpp23 project to the solution. |
build_test_all.cmd |
Builds test_cpp23 as part of the “build all tests” script. |
run_tests.cmd |
Runs test_cpp23 as part of the test runner script. |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
When using lambda coroutines as delegates, care must be taken that the lifetime of captured objects may be shorter than that of the coroutine, see #766 (comment). This issue has a better solution in C++23, which is to use explicit object parameters to copy the captures into the coroutine frame. However, this feature is currently not available in C++/WinRT.
The following code fails to compile with an error that the copy constructor has been deleted.
The reason is that the final type
delegateinherits from the handler (lambda), and code_writers.h#L2619 uses the typedelegate(*thisin theInvokemember function ofdelegate) to calloperator(), causingthis(explicit parameter of lambda) to be deduced asdelegate. Sincedelegateis non-copyable,operator()cannot be called. This change makesInvokeuse the original lambda's type to calloperator(), sothisis deduced as the lambda's type, resolving the issue.Because of the purpose is to copy the captured object into the coroutine frame, the slicing that occurs here is intentional, and there is no need to copy the complete
delegateobject.