Skip to content

It would be nice if event registrations could take weak_from_this() for shared_ptr in addition to get_weak() #1316

@dmachaj

Description

@dmachaj

Version

2.0.220131.2

Summary

class MyClass : public std::enable_shared_from_this<MyClass>
{
  MyClass() = default;
  void Initialize();
  void OnThingHappened(auto& thingSender, auto& thingArgs);
};

Somewhere in MyClass implementation:

void Initialize()
{
  const auto object = getObjectSomewhere();
  auto revoker = object.OnThing(winrt::auto_revoke, {weak_from_this(), &MyClass::OnThingHappened});
}

The code gen for the delegate is roughly:

    struct ThingHappenedHandler : winrt::Windows::Foundation::IUnknown
    {
        ThingHappenedHandler(std::nullptr_t = nullptr) noexcept {}
        ThingHappenedHandler(void* ptr, take_ownership_from_abi_t) noexcept : winrt::Windows::Foundation::IUnknown(ptr, take_ownership_from_abi) {}
        template <typename L> ThingHappenedHandler(L lambda);
        template <typename F> ThingHappenedHandler(F* function);
        template <typename O, typename M> ThingHappenedHandler(O* object, M method);
        template <typename O, typename M> ThingHappenedHandler(com_ptr<O>&& object, M method);
        template <typename O, typename M> ThingHappenedHandler(weak_ref<O>&& object, M method);
        auto operator()(winrt::ThingArgs const& args) const;
    };

It would be nice if that list of methods also had:

template <typename O, typename M> ThingHappenedHandler(std::weak_ptr<O>&& object, M method);

(This would need some sort of inclusion guard so that projects which do not include or use std::shared_ptr and std::weak_ptr will not require those headers to be included.)

The use case for this is a code base that is using pure C++ as much as possible while also calling some WinRT APIs. I want to be able to safely pass weak pointers for event callbacks to avoid races and use-after-free problems. However, I think that would require the class with the callback to derive from winrt::implements. That is possible but it would be ideal to not have to change it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions