Skip to content

Commit

Permalink
Add a clang-specific impl->projection conversion operator (#1274)
Browse files Browse the repository at this point in the history
  • Loading branch information
DHowett authored Feb 23, 2023
1 parent abcdc75 commit 72b30cc
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 0 deletions.
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());
}

0 comments on commit 72b30cc

Please sign in to comment.