Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions strings/base_implements.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,25 @@ namespace winrt::impl
template <typename D, typename I, typename Enable>
struct producer_convert : producer<D, typename default_interface<I>::type>
{
#ifdef __clang__
// This is sub-optimal in that it requires an AddRef and Release of the
// implementation type for every conversion, but it works around an
// issue where Clang ignores the conversion of producer_ref<I> const
// to I&& (an rvalue ref that cannot bind a const rvalue).
// See CWG rev. 110 active issue 2077, "Overload resolution and invalid
// rvalue-reference initialization"
operator I() const noexcept
{
I result{ nullptr };
copy_from_abi(result, (produce<D, typename default_interface<I>::type>*)this);
return result;
}
#else
operator producer_ref<I> const() const noexcept
{
return { (produce<D, typename default_interface<I>::type>*)this };
}
#endif

operator producer_vtable<I> const() const noexcept
{
Expand Down
10 changes: 10 additions & 0 deletions test/old_tests/UnitTests/as_implements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,13 @@ TEST_CASE("as_implements_inheritance")
REQUIRE(bar.get() == foo2.get());
}
}

TEST_CASE("convert_to_implements_via_uniform_initialization")
{
// uniform initialization relies on IStringable(IStringable&&),
// which requires non-const rvalue semantics.
com_ptr<Foo> foo = make_self<Foo>();
IStringable stringable{ *foo };
com_ptr<Foo> foo2 = stringable.as<Foo>();
REQUIRE(foo.get() == foo2.get());
}