microsoft / cppwinrt

C++/WinRT
MIT License
1.67k stars 242 forks source link

Feature Request: IKeyValuePair function template #1089

Closed tom-huntington closed 2 years ago

tom-huntington commented 2 years ago

It would be most convenient to be able to create a IKeyValuePair<K, V> to pass information between UserControls without having to define a winrt type in idl.

sylveon commented 2 years ago

You can use winrt::implements to avoid declaring a type in IDL:

#include <winrt/Windows.Foundation.Collections.h>

struct foo : winrt::implements<foo, winrt::Windows::Foundation::Collections::IKeyValuePair<int, int>>
{
    int Key() { return 1; }
    int Value() { return 2; }
};

// some API that takes IKVP
void Bar(winrt::Windows::Foundation::Collections::IKeyValuePair<int, int> const&);

int main()
{
    auto kvp = winrt::make<foo>();
    Bar(kvp);
}
tom-huntington commented 2 years ago

Thanks, I'll have a play. Maybe this should have been an SO question.

Also, I could just use IObservableMap, so feel to close this. Although this style is more python/JS than c++.

tom-huntington commented 2 years ago

I'm going to use IObservableMap<winrt::hstring, IInspectable> for now. Using winrt::implements to make a pair is a bit cumbersome since you cant do it generically .

Although, nesting IKeyValuePair<K, V> is the style I'd like to program in.

It would also be nice if the windows runtime supported a std::variant type (and maybe std::tuple) that so that you can make any algebraic data type from the existing types of the windows runtime.

tom-huntington commented 2 years ago
namespace winrt
{
template <typename K, typename V>
struct pair_impl : implements<pair_impl<K,V>, Windows::Foundation::Collections::IKeyValuePair<K,V>>
{
    pair_impl(K k, V v) : m_k(k), m_v(v) {}
    K Key() { return m_k; }
    V Value() { return m_v; }
private:
    K m_k;
    V m_v;
};

template <typename K, typename V>
Windows::Foundation::Collections::IKeyValuePair<K, V> pair(K key, V value)
{
    return make<pair_impl<K, V>>(key, value);
}
}

int main()
{
    using winrt::Windows::Foundation::Collections::IKeyValuePair;
    auto pair = winrt::pair<int, int>(1, 1);
    auto pair_of_pairs = winrt::pair<IKeyValuePair<int, int>, IKeyValuePair<int, int>>(pair, pair);
    ...
}
tom-huntington commented 2 years ago

I've realized that converting the UserControls projection type back to it's implementation type (https://devblogs.microsoft.com/oldnewthing/20200828-00/?p=104138) is a better way to export information from a UserConrol than creating windows runtime Algebraic Data Types.

sylveon commented 2 years ago

Yup! That's the best way to have "internal" methods like C++/CX and C#