Skip to content

Deducing this for delegates#1553

Open
YexuanXiao wants to merge 3 commits intomicrosoft:masterfrom
YexuanXiao:deducting-this-upstream
Open

Deducing this for delegates#1553
YexuanXiao wants to merge 3 commits intomicrosoft:masterfrom
YexuanXiao:deducting-this-upstream

Conversation

@YexuanXiao
Copy link
Contributor

@YexuanXiao YexuanXiao commented Mar 23, 2026

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.

#include <winrt/Windows.Foundation.Collections.h>
using namespace winrt::Windows::Foundation::Collections;

int main()
{
	int called{};
	int sum{};

	auto vector = winrt::single_threaded_observable_vector<int>();
	auto revoker = vector.VectorChanged(winrt::auto_revoke, 
		[called, sum](this auto, IObservableVector<int>, IVectorChangedEventArgs)
		{
		});
}

The reason is that the final type delegate inherits from the handler (lambda), and code_writers.h#L2619 uses the type delegate (*this in the Invoke member function of delegate) to call operator(), causing this (explicit parameter of lambda) to be deduced as delegate. Since delegate is non-copyable, operator() cannot be called. This change makes Invoke use the original lambda's type to call operator(), so this is 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 delegate object.

@YexuanXiao
Copy link
Contributor Author

YexuanXiao commented Mar 23, 2026

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, this is observed to be X, while in the assignment operator at L108, this is observed to be X+16 (in bytes). Therefore, this is undoubtedly a Clang bug rather than a test bug. As a result, I will disable the test observablevector_vectorchanged for Clang target x86.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants