From 1b4ea75d26488dc815ec9aba25aefe5e3a2405fc Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com.> Date: Wed, 13 Nov 2024 12:11:41 -0800 Subject: [PATCH 1/8] Stop originating error context in try_as and use a new try_as_reason instead for consume methods --- cppwinrt/code_writers.h | 12 ++++++------ strings/base_error.h | 19 +++---------------- strings/base_implements.h | 6 ++++++ strings/base_windows.h | 27 +++++++++++++++++++++++---- 4 files changed, 38 insertions(+), 26 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index f93279a74..f3cfa3c83 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1137,9 +1137,9 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const [castedResult, code] = static_cast(this)->template try_as_reason<%>(); + check_cast_result(code); auto const abiType = *(abi_t<%>**)&castedResult; - check_cast_result(abiType); abiType->%(%); } else @@ -1156,9 +1156,9 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const [castedResult, code] = static_cast(this)->template try_as_reason<%>(); + check_cast_result(code); auto const abiType = *(abi_t<%>**)&castedResult; - check_cast_result(abiType); WINRT_VERIFY_(0, abiType->%(%)); } else @@ -1176,9 +1176,9 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const [castedResult, code] = static_cast(this)->template try_as_reason<%>(); + check_cast_result(code); auto const abiType = *(abi_t<%>**)&castedResult; - check_cast_result(abiType); check_hresult(abiType->%(%)); } else diff --git a/strings/base_error.h b/strings/base_error.h index 9b9624277..773b6b912 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -539,24 +539,11 @@ namespace winrt::impl return result; } - inline WINRT_IMPL_NOINLINE void check_cast_result(void* from, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) + inline WINRT_IMPL_NOINLINE void check_cast_result(hresult const result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { - if (!from) + if (result != 0) { - com_ptr restrictedError; - if (WINRT_IMPL_GetRestrictedErrorInfo(restrictedError.put_void()) == 0) - { - WINRT_IMPL_SetRestrictedErrorInfo(restrictedError.get()); - - int32_t code; - impl::bstr_handle description; - impl::bstr_handle restrictedDescription; - impl::bstr_handle capabilitySid; - if (restrictedError->GetErrorDetails(description.put(), &code, restrictedDescription.put(), capabilitySid.put()) == 0) - { - throw hresult_error(code, take_ownership_from_abi, sourceInformation); - } - } + throw hresult_error(result, take_ownership_from_abi, sourceInformation); } } } diff --git a/strings/base_implements.h b/strings/base_implements.h index d0bb09012..af5e7a45b 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -788,6 +788,12 @@ namespace winrt::impl return m_inner.try_as(); } + template + auto try_as_reason() const noexcept + { + return m_inner.try_as_reason(); + } + explicit operator bool() const noexcept { return m_inner.operator bool(); diff --git a/strings/base_windows.h b/strings/base_windows.h index f5230e1c8..b6e7e2f88 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -128,12 +128,25 @@ namespace winrt::impl } void* result{}; - hresult code = ptr->QueryInterface(guid_of(), &result); - if (code < 0) + ptr->QueryInterface(guid_of(), &result); + return wrap_as_result(result); + } + + template , int> = 0> + std::pair, hresult> try_as_reason(From* ptr) noexcept + { +#ifdef WINRT_DIAGNOSTICS + get_diagnostics_info().add_query(); +#endif + + if (!ptr) { - WINRT_IMPL_RoCaptureErrorContext(code); + return { nullptr, 0 }; } - return wrap_as_result(result); + + void* result{}; + hresult code = ptr->QueryInterface(guid_of(), &result); + return { wrap_as_result(result), code }; } } @@ -209,6 +222,12 @@ WINRT_EXPORT namespace winrt::Windows::Foundation return impl::try_as(m_ptr); } + template + auto try_as_reason() const noexcept + { + return impl::try_as_reason(m_ptr); + } + template void as(To& to) const { From 00cdba27e11866c3cfef965da68dbaf9bdc35bac Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com.> Date: Wed, 13 Nov 2024 12:36:02 -0800 Subject: [PATCH 2/8] Rename to try_as_with_reason and remove now unused combase linkage --- cppwinrt/code_writers.h | 6 +++--- strings/base_extern.h | 2 -- strings/base_implements.h | 4 ++-- strings/base_windows.h | 6 +++--- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index f3cfa3c83..619eac68d 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1137,7 +1137,7 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [castedResult, code] = static_cast(this)->template try_as_reason<%>(); + auto const [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); check_cast_result(code); auto const abiType = *(abi_t<%>**)&castedResult; abiType->%(%); @@ -1156,7 +1156,7 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [castedResult, code] = static_cast(this)->template try_as_reason<%>(); + auto const [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); check_cast_result(code); auto const abiType = *(abi_t<%>**)&castedResult; WINRT_VERIFY_(0, abiType->%(%)); @@ -1176,7 +1176,7 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [castedResult, code] = static_cast(this)->template try_as_reason<%>(); + auto const [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); check_cast_result(code); auto const abiType = *(abi_t<%>**)&castedResult; check_hresult(abiType->%(%)); diff --git a/strings/base_extern.h b/strings/base_extern.h index c0e83e75a..2412f9f2c 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -32,8 +32,6 @@ extern "C" int32_t __stdcall WINRT_IMPL_RoCaptureErrorContext(int32_t error) noexcept WINRT_IMPL_LINK(RoCaptureErrorContext, 4); void __stdcall WINRT_IMPL_RoFailFastWithErrorContext(int32_t) noexcept WINRT_IMPL_LINK(RoFailFastWithErrorContext, 4); int32_t __stdcall WINRT_IMPL_RoTransformError(int32_t, int32_t, void*) noexcept WINRT_IMPL_LINK(RoTransformError, 12); - int32_t __stdcall WINRT_IMPL_GetRestrictedErrorInfo(void**) noexcept WINRT_IMPL_LINK(GetRestrictedErrorInfo, 4); - int32_t __stdcall WINRT_IMPL_SetRestrictedErrorInfo(void*) noexcept WINRT_IMPL_LINK(SetRestrictedErrorInfo, 4); void* __stdcall WINRT_IMPL_LoadLibraryExW(wchar_t const* name, void* unused, uint32_t flags) noexcept WINRT_IMPL_LINK(LoadLibraryExW, 12); int32_t __stdcall WINRT_IMPL_FreeLibrary(void* library) noexcept WINRT_IMPL_LINK(FreeLibrary, 4); diff --git a/strings/base_implements.h b/strings/base_implements.h index af5e7a45b..4bd60e5f0 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -789,9 +789,9 @@ namespace winrt::impl } template - auto try_as_reason() const noexcept + auto try_as_with_reason() const noexcept { - return m_inner.try_as_reason(); + return m_inner.try_as_with_reason(); } explicit operator bool() const noexcept diff --git a/strings/base_windows.h b/strings/base_windows.h index b6e7e2f88..6fa2e17d0 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -133,7 +133,7 @@ namespace winrt::impl } template , int> = 0> - std::pair, hresult> try_as_reason(From* ptr) noexcept + std::pair, hresult> try_as_with_reason(From* ptr) noexcept { #ifdef WINRT_DIAGNOSTICS get_diagnostics_info().add_query(); @@ -223,9 +223,9 @@ WINRT_EXPORT namespace winrt::Windows::Foundation } template - auto try_as_reason() const noexcept + auto try_as_with_reason() const noexcept { - return impl::try_as_reason(m_ptr); + return impl::try_as_with_reason(m_ptr); } template From 08f23eab41325ed237c39a5ba368c6dde22b590d Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com.> Date: Wed, 13 Nov 2024 13:10:27 -0800 Subject: [PATCH 3/8] Remove check_cast_result in favor of check_hresult now that they are the same code --- cppwinrt/code_writers.h | 8 ++++---- strings/base_error.h | 8 -------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 619eac68d..1c7650403 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1130,7 +1130,7 @@ namespace cppwinrt { // we intentionally ignore errors when unregistering event handlers to be consistent with event_revoker // - // The `noexcept` versions will crash if check_cast_result throws but that is no different than previous + // The `noexcept` versions will crash if check_hresult throws but that is no different than previous // behavior where it would not check the cast result and nullptr crash. At least the exception will terminate // immediately while preserving the error code and local variables. format = R"( template auto consume_%::%(%) const noexcept @@ -1138,7 +1138,7 @@ namespace cppwinrt if constexpr (!std::is_same_v) { auto const [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); - check_cast_result(code); + check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; abiType->%(%); } @@ -1157,7 +1157,7 @@ namespace cppwinrt if constexpr (!std::is_same_v) { auto const [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); - check_cast_result(code); + check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; WINRT_VERIFY_(0, abiType->%(%)); } @@ -1177,7 +1177,7 @@ namespace cppwinrt if constexpr (!std::is_same_v) { auto const [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); - check_cast_result(code); + check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; check_hresult(abiType->%(%)); } diff --git a/strings/base_error.h b/strings/base_error.h index 773b6b912..85de70f63 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -538,14 +538,6 @@ namespace winrt::impl } return result; } - - inline WINRT_IMPL_NOINLINE void check_cast_result(hresult const result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) - { - if (result != 0) - { - throw hresult_error(result, take_ownership_from_abi, sourceInformation); - } - } } #undef WINRT_IMPL_RETURNADDRESS From d4d57330a7e841eee318da9d6a66255bbb12c6bd Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com.> Date: Wed, 13 Nov 2024 16:17:00 -0800 Subject: [PATCH 4/8] Add back reference to structured binding to re-eliminate spurious addref/release that is increasing binary size --- cppwinrt/code_writers.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 1c7650403..72907b317 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1137,7 +1137,7 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); + auto const& [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; abiType->%(%); @@ -1156,7 +1156,7 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); + auto const& [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; WINRT_VERIFY_(0, abiType->%(%)); @@ -1176,7 +1176,7 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); + auto const& [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; check_hresult(abiType->%(%)); From 96f637e7338324c44326c0b06ab3db1d032f0008 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com.> Date: Wed, 13 Nov 2024 17:06:09 -0800 Subject: [PATCH 5/8] Remove try_as_with_reason and just call as --- cppwinrt/code_writers.h | 11 ++++------- strings/base_implements.h | 8 ++++---- strings/base_windows.h | 23 ----------------------- 3 files changed, 8 insertions(+), 34 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 72907b317..e942dd321 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1130,15 +1130,14 @@ namespace cppwinrt { // we intentionally ignore errors when unregistering event handlers to be consistent with event_revoker // - // The `noexcept` versions will crash if check_hresult throws but that is no different than previous + // The `noexcept` versions will crash if .as<>() throws but that is no different than previous // behavior where it would not check the cast result and nullptr crash. At least the exception will terminate // immediately while preserving the error code and local variables. format = R"( template auto consume_%::%(%) const noexcept {% if constexpr (!std::is_same_v) { - auto const& [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); - check_hresult(code); + auto const& castedResult = static_cast(this)->template as<%>(); auto const abiType = *(abi_t<%>**)&castedResult; abiType->%(%); } @@ -1156,8 +1155,7 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const& [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); - check_hresult(code); + auto const& castedResult = static_cast(this)->template as<%>(); auto const abiType = *(abi_t<%>**)&castedResult; WINRT_VERIFY_(0, abiType->%(%)); } @@ -1176,8 +1174,7 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const& [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); - check_hresult(code); + auto const& castedResult = static_cast(this)->template as<%>(); auto const abiType = *(abi_t<%>**)&castedResult; check_hresult(abiType->%(%)); } diff --git a/strings/base_implements.h b/strings/base_implements.h index 4bd60e5f0..7f7ec9393 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -783,15 +783,15 @@ namespace winrt::impl struct WINRT_IMPL_EMPTY_BASES root_implements_composing_outer { template - auto try_as() const noexcept + auto as() const noexcept { - return m_inner.try_as(); + return m_inner.as(); } template - auto try_as_with_reason() const noexcept + auto try_as() const noexcept { - return m_inner.try_as_with_reason(); + return m_inner.try_as(); } explicit operator bool() const noexcept diff --git a/strings/base_windows.h b/strings/base_windows.h index 6fa2e17d0..41030d368 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -131,23 +131,6 @@ namespace winrt::impl ptr->QueryInterface(guid_of(), &result); return wrap_as_result(result); } - - template , int> = 0> - std::pair, hresult> try_as_with_reason(From* ptr) noexcept - { -#ifdef WINRT_DIAGNOSTICS - get_diagnostics_info().add_query(); -#endif - - if (!ptr) - { - return { nullptr, 0 }; - } - - void* result{}; - hresult code = ptr->QueryInterface(guid_of(), &result); - return { wrap_as_result(result), code }; - } } WINRT_EXPORT namespace winrt::Windows::Foundation @@ -222,12 +205,6 @@ WINRT_EXPORT namespace winrt::Windows::Foundation return impl::try_as(m_ptr); } - template - auto try_as_with_reason() const noexcept - { - return impl::try_as_with_reason(m_ptr); - } - template void as(To& to) const { From 6d4d14a4bd6df46a6aa16d226ced383ba61fb13a Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com.> Date: Wed, 13 Nov 2024 17:20:17 -0800 Subject: [PATCH 6/8] Revert "Remove try_as_with_reason and just call as" This reverts commit 96f637e7338324c44326c0b06ab3db1d032f0008. --- cppwinrt/code_writers.h | 11 +++++++---- strings/base_implements.h | 8 ++++---- strings/base_windows.h | 23 +++++++++++++++++++++++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index e942dd321..72907b317 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1130,14 +1130,15 @@ namespace cppwinrt { // we intentionally ignore errors when unregistering event handlers to be consistent with event_revoker // - // The `noexcept` versions will crash if .as<>() throws but that is no different than previous + // The `noexcept` versions will crash if check_hresult throws but that is no different than previous // behavior where it would not check the cast result and nullptr crash. At least the exception will terminate // immediately while preserving the error code and local variables. format = R"( template auto consume_%::%(%) const noexcept {% if constexpr (!std::is_same_v) { - auto const& castedResult = static_cast(this)->template as<%>(); + auto const& [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); + check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; abiType->%(%); } @@ -1155,7 +1156,8 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const& castedResult = static_cast(this)->template as<%>(); + auto const& [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); + check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; WINRT_VERIFY_(0, abiType->%(%)); } @@ -1174,7 +1176,8 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const& castedResult = static_cast(this)->template as<%>(); + auto const& [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); + check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; check_hresult(abiType->%(%)); } diff --git a/strings/base_implements.h b/strings/base_implements.h index 7f7ec9393..4bd60e5f0 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -783,15 +783,15 @@ namespace winrt::impl struct WINRT_IMPL_EMPTY_BASES root_implements_composing_outer { template - auto as() const noexcept + auto try_as() const noexcept { - return m_inner.as(); + return m_inner.try_as(); } template - auto try_as() const noexcept + auto try_as_with_reason() const noexcept { - return m_inner.try_as(); + return m_inner.try_as_with_reason(); } explicit operator bool() const noexcept diff --git a/strings/base_windows.h b/strings/base_windows.h index 41030d368..6fa2e17d0 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -131,6 +131,23 @@ namespace winrt::impl ptr->QueryInterface(guid_of(), &result); return wrap_as_result(result); } + + template , int> = 0> + std::pair, hresult> try_as_with_reason(From* ptr) noexcept + { +#ifdef WINRT_DIAGNOSTICS + get_diagnostics_info().add_query(); +#endif + + if (!ptr) + { + return { nullptr, 0 }; + } + + void* result{}; + hresult code = ptr->QueryInterface(guid_of(), &result); + return { wrap_as_result(result), code }; + } } WINRT_EXPORT namespace winrt::Windows::Foundation @@ -205,6 +222,12 @@ WINRT_EXPORT namespace winrt::Windows::Foundation return impl::try_as(m_ptr); } + template + auto try_as_with_reason() const noexcept + { + return impl::try_as_with_reason(m_ptr); + } + template void as(To& to) const { From 88a826c97d5c06384f0d1e2146f1a797b0ec1a0c Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com.> Date: Thu, 14 Nov 2024 14:07:08 -0800 Subject: [PATCH 7/8] retrigger checks From f06e88b39814215c4f15abe0314e69922d0464a1 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com.> Date: Thu, 14 Nov 2024 16:32:26 -0800 Subject: [PATCH 8/8] Raymond's suggestion to mark try_as_with_reason as private so composed classes dont see it --- cppwinrt/code_writers.h | 6 +++--- strings/base_implements.h | 17 +++++++++++------ strings/base_windows.h | 6 ++++++ 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 72907b317..01f7dea10 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1137,7 +1137,7 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const& [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); + auto const [castedResult, code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; abiType->%(%); @@ -1156,7 +1156,7 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const& [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); + auto const [castedResult, code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; WINRT_VERIFY_(0, abiType->%(%)); @@ -1176,7 +1176,7 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const& [castedResult, code] = static_cast(this)->template try_as_with_reason<%>(); + auto const [castedResult, code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; check_hresult(abiType->%(%)); diff --git a/strings/base_implements.h b/strings/base_implements.h index 4bd60e5f0..0847f5019 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -788,19 +788,24 @@ namespace winrt::impl return m_inner.try_as(); } - template - auto try_as_with_reason() const noexcept - { - return m_inner.try_as_with_reason(); - } - explicit operator bool() const noexcept { return m_inner.operator bool(); } + + template + friend auto winrt::impl::try_as_with_reason(From ptr) noexcept; + protected: static constexpr bool is_composing = true; Windows::Foundation::IInspectable m_inner; + + private: + template + auto try_as_with_reason() const noexcept + { + return m_inner.try_as_with_reason(); + } }; template diff --git a/strings/base_windows.h b/strings/base_windows.h index 6fa2e17d0..a67ef0b20 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -148,6 +148,12 @@ namespace winrt::impl hresult code = ptr->QueryInterface(guid_of(), &result); return { wrap_as_result(result), code }; } + + template + auto try_as_with_reason(From ptr) noexcept + { + return ptr->template try_as_with_reason(); + } } WINRT_EXPORT namespace winrt::Windows::Foundation