取消对带有转换的c++/winrt中的数值进行装箱



有没有一种方法可以取消对数值的装箱,而不管其类型如何?例如,装箱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

如果你不知道(或者不在乎(哪种类型的值被装箱了,那么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提供模板专业化应该是一个简单的练习(尽管有点重复/乏味(。

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...

要实现一种不考虑类型而取消数值框的方法,可以尝试将自动类型转换封装到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);

最新更新