@@ -261,6 +261,95 @@ WINRT_EXPORT namespace winrt::Windows::Foundation
261261 }
262262}
263263
264+ namespace winrt ::impl
265+ {
266+ template <typename T, typename From>
267+ T unbox_value_type (From&& value)
268+ {
269+ static_assert (!is_com_interface_v<T>);
270+
271+ if (!value)
272+ {
273+ throw hresult_no_interface ();
274+ }
275+ if constexpr (std::is_enum_v<T>)
276+ {
277+ if (auto temp = value.try_as <Windows::Foundation::IReference<T>>())
278+ {
279+ return temp.Value ();
280+ }
281+ else
282+ {
283+ return static_cast <T>(value.as <Windows::Foundation::IReference<std::underlying_type_t <T>>>().Value ());
284+ }
285+ }
286+ #ifdef WINRT_IMPL_IUNKNOWN_DEFINED
287+ else if constexpr (std::is_same_v<T, GUID>)
288+ {
289+ return value.as <Windows::Foundation::IReference<guid>>().Value ();
290+ }
291+ #endif
292+ else
293+ {
294+ return value.as <Windows::Foundation::IReference<T>>().Value ();
295+ }
296+ }
297+
298+ template <typename T, typename Ret = T, typename From, typename U>
299+ Ret unbox_value_type_or (From&& value, U&& default_value)
300+ {
301+ if constexpr (std::is_enum_v<T>)
302+ {
303+ if (auto temp = value.try_as <Windows::Foundation::IReference<T>>())
304+ {
305+ return temp.Value ();
306+ }
307+
308+ if (auto temp = value.try_as <Windows::Foundation::IReference<std::underlying_type_t <T>>>())
309+ {
310+ return static_cast <T>(temp.Value ());
311+ }
312+ }
313+ #ifdef WINRT_IMPL_IUNKNOWN_DEFINED
314+ else if constexpr (std::is_same_v<T, GUID>)
315+ {
316+ if (auto temp = value.try_as <Windows::Foundation::IReference<guid>>())
317+ {
318+ return temp.Value ();
319+ }
320+ }
321+ #endif
322+ else
323+ {
324+ if (auto temp = value.try_as <Windows::Foundation::IReference<T>>())
325+ {
326+ return temp.Value ();
327+ }
328+ }
329+ return default_value;
330+ }
331+
332+ template <typename To, typename From, std::enable_if_t <!is_com_interface_v<To>, int >>
333+ auto as (From* ptr)
334+ {
335+ if constexpr (impl::is_com_interface_v<From>)
336+ {
337+ return unbox_value_type<To>(reinterpret_cast <Windows::Foundation::IUnknown const &>(ptr));
338+ }
339+ else
340+ {
341+ return unbox_value_type<To>(reinterpret_cast <com_ptr<From> const &>(ptr));
342+ }
343+ }
344+
345+ template <typename To, typename From, std::enable_if_t <!is_com_interface_v<To>, int >>
346+ auto try_as (From* ptr) noexcept
347+ {
348+ using type = std::conditional_t <impl::is_com_interface_v<From>, Windows::Foundation::IUnknown, com_ptr<From>>;
349+ return unbox_value_type_or<To, std::optional<To>>(reinterpret_cast <type const &>(ptr), std::nullopt );
350+ }
351+ }
352+
264353WINRT_EXPORT namespace winrt
265354{
266355 inline Windows::Foundation::IInspectable box_value (param::hstring const & value)
@@ -290,31 +379,7 @@ WINRT_EXPORT namespace winrt
290379 }
291380 else
292381 {
293- if (!value)
294- {
295- throw hresult_no_interface ();
296- }
297- if constexpr (std::is_enum_v<T>)
298- {
299- if (auto temp = value.try_as <Windows::Foundation::IReference<T>>())
300- {
301- return temp.Value ();
302- }
303- else
304- {
305- return static_cast <T>(value.as <Windows::Foundation::IReference<std::underlying_type_t <T>>>().Value ());
306- }
307- }
308- #ifdef WINRT_IMPL_IUNKNOWN_DEFINED
309- else if constexpr (std::is_same_v<T, GUID>)
310- {
311- return value.as <Windows::Foundation::IReference<guid>>().Value ();
312- }
313- #endif
314- else
315- {
316- return value.as <Windows::Foundation::IReference<T>>().Value ();
317- }
382+ return impl::unbox_value_type<T>(value);
318383 }
319384 }
320385
@@ -344,36 +409,11 @@ WINRT_EXPORT namespace winrt
344409 return temp;
345410 }
346411 }
347- else if constexpr (std::is_enum_v<T>)
348- {
349- if (auto temp = value.try_as <Windows::Foundation::IReference<T>>())
350- {
351- return temp.Value ();
352- }
353-
354- if (auto temp = value.try_as <Windows::Foundation::IReference<std::underlying_type_t <T>>>())
355- {
356- return static_cast <T>(temp.Value ());
357- }
358- }
359- #ifdef WINRT_IMPL_IUNKNOWN_DEFINED
360- else if constexpr (std::is_same_v<T, GUID>)
361- {
362- if (auto temp = value.try_as <Windows::Foundation::IReference<guid>>())
363- {
364- return temp.Value ();
365- }
366- }
367- #endif
368412 else
369413 {
370- if (auto temp = value.try_as <Windows::Foundation::IReference<T>>())
371- {
372- return temp.Value ();
373- }
414+ return impl::unbox_value_type_or<T>(value, default_value);
374415 }
375416 }
376-
377417 return default_value;
378418 }
379419
0 commit comments