Search code examples
c++c++-winrt

Unbox numerical value in c++/winrt with conversion


Is there a way to unbox numerical value regardless of type? For ex. boxing int and then unboxing double or long long (if the conversion is possible). The point is to be able to unbox from some unknown type to known type if the conversion is possible.

Now it behaves like this:

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

And I would like to have something like this:

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

Solution

  • If you don't know (or don't care) which type of value has been boxed, IReference<T> won't be fun to use. Chaining a bunch of unbox_value/unbox_value_or calls will incur a series of QueryInterface calls, which is a very inefficient way to do this. Better, would be to use IPropertyValue. It already performs scalar conversions, and handles errors like overflow.

    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();
    

    If you prefer, it should be a simple (if slightly repetitive/tedious) exercise to provide the template specializations for your 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...