通过转换在 c++/winrt 中取消装箱数值

Unbox numerical value in c++/winrt with conversion

有没有办法不考虑类型对数值进行拆箱?对于前。装箱 int,然后拆箱 doublelong long(如果可以转换)。重点是能够从某种未知类型拆箱到已知类型(如果可以进行转换)。

现在它的行为是这样的:

winrt::Windows::Foundation::IInspectable boxed_value = winrt::box_value(30);
int i = winrt::unbox_value<int>(boxed_value); //OK
double d = winrt::unbox_value<double>(boxed_value); //Exception

我想要这样的东西:

winrt::Windows::Foundation::IInspectable boxed_value = winrt::box_value(30);
int i = unbox_value_with_conversion<int>(boxed_value); //OK
double d = unbox_value_with_conversion<double>(boxed_value); //OK

要实现一种无论类型如何对数值进行拆箱的方法,您可以尝试将自动类型转换包装到 unbox_value_with_conversion 方法中,以您提到的 int、double 和 long long 类型为例。

函数声明

template<class T>

T unbox_value_with_conversion(winrt::Windows::Foundation::IInspectable const& value);

函数定义

template<class T>

inline T MainPage::unbox_value_with_conversion(winrt::Windows::Foundation::IInspectable const& value)
{
    T res{};
    auto vv = value.as<winrt::Windows::Foundation::IPropertyValue>();
    if (vv.Type() == winrt::Windows::Foundation::PropertyType::Int32)
    {
        int32_t tt = vv.as<int32_t>();
        res = (T)tt;
        return res;
    }
    if (vv.Type() == winrt::Windows::Foundation::PropertyType::Double)
    {
        double dd = vv.as<double>();
        res = (T)dd;
        return res;
    }
    if (vv.Type() == winrt::Windows::Foundation::PropertyType::Int64)
    {
        long long llong = vv.as<long long>();
        res = (T)llong;
        return res;
    }
    return T();
}

类型转换

winrt::Windows::Foundation::IInspectable boxed_value1 = winrt::box_value(30);
double dd1 = unbox_value_with_conversion<double>(boxed_value1);
long long llong1= unbox_value_with_conversion<long long>(boxed_value1);

如果您不知道(或不关心)哪种类型的值被装箱,IReference<T> 使用起来不会很有趣。链接一堆 unbox_value/unbox_value_or 调用将引发一系列 QueryInterface 调用,这是一种非常低效的方法。更好的方法是使用 IPropertyValue。它已经执行标量转换,并处理溢出等错误。

winrt::Windows::Foundation::IInspectable boxed_value = winrt::box_value(30);
int i = boxed_value.as<winrt::Windows::Foundation::IPropertyValue>().GetInt32();
double d = boxed_value.as<winrt::Windows::Foundation::IPropertyValue>().GetDouble();

如果您愿意,为您的 unbox_value_with_conversion.

提供模板专业化应该是一个简单的(如果稍微 repetitive/tedious)练习
template <typename T>
T unbox_value_with_conversion(winrt::Windows::Foundation::IInspectable const& value)
{
  return winrt::unbox_value<T>(value);
}

template <>
int32_t unbox_value_with_conversion<int32_t>(winrt::Windows::Foundation::IInspectable const& value)
{
  return value.as<winrt::Windows::Foundation::IPropertyValue>().GetInt32();
}

// Rest of specializations...