Passing parameters to projected APIs
For certain types, C++/WinRT provides alternative methods for passing a parameter to a projected API. These parameter-accepting classes are placed in the winrt::param namespace. Only C++/WinRT-generated code should use these classes; don't use them in your own functions and methods.
Important
You shouldn't use the types in the winrt::param namespace yourself. They're for the benefit of the projection.
Some of these alternative distinguish between synchronous and asynchronous calls. The version for asynchronous calls typically takes ownership of the parameter data to ensure that the values remain valid and unchanged until the asynchronous call completes. Note, however, that this protection does not extend to changes to the collection from another thread. Preventing that is your responsibility.
Alternatives for string parameters
winrt::param::hstring simplifies passing parameters as winrt::hstring. In addition to winrt::hstring, these alternatives are also accepted:
Alternative | Notes |
---|---|
{} |
An empty string. |
std::wstring_view | The view must be followed by a null terminator. |
std::wstring | |
wchar_t const* | A null-terminated string. |
You can't pass nullptr
to represent the empty string. Instead, use L""
or {}
.
The compiler knows how to evaluate wcslen
on string literals at compile time. So, for literals, L"Name"sv
and L"Name"
are equivalent.
Note that std::wstring_view objects are not null-terminated, but C++/WinRT requires that the character after the end of the view be a null. If you pass a non-null-terminated std::wstring_view, then the process will terminate.
Alternatives for iterable parameters
winrt::param::iterable<T> and winrt::param::async_iterable<T> simplify passing parameters as IIterable<T>.
The Windows Runtime collections IVector<T> and IVectorView<T> already support IIterable<T>. The Windows Runtime collections IMap<K, V> and IMapView<K, V> already support IIterable<IKeyValuePair<K, V>>.
In addition to IIterable<T>, the following alternatives are also accepted. Note that some alternatives are available only for synchronous methods.
Alternative | Sync | Async | Notes |
---|---|---|---|
std::vector<T> const& | Yes | No | |
std::vector<T>&& | Yes | Yes | Contents are moved into a temporary iterable. |
std::initializer_list<T> | Yes | Yes | Async version copies the items. |
std::initializer_list<U> | Yes | No | U must be convertible to T. |
{ begin, end } |
Yes | No | begin and end must be forward iterators, and *begin must be convertible to T. |
The double-iterator works more generally for the case where you have a collection that doesn't fit any of the scenarios above, as long as you can iterate over it and produce things that can be converted to T. For example, you may have a IVector<U> or std::vector<U>, where U is convertible to T.
In the following example, the SetStorageItems method expects an IIterable<IStorageItem>. The double-iterator pattern lets us pass other types of collections.
// IVector of derived types.
winrt::Windows::Foundation::Collections::IVector<winrt::Windows::Storage::StorageFile>
storageFiles{ /* initialization elided */ };
dataPackage.SetStorageItems(storageFiles); // doesn't work
dataPackage.SetStorageItems({ storageFiles.begin(), storageFiles.end() }); // works
// Array of derived types.
std::array<winrt::Windows::Storage::StorageFile, 3>
storageFiles{ /* initialization elided */ };
dataPackage.SetStorageItems(storageFiles); // doesn't work
dataPackage.SetStorageItems({ storageFiles.begin(), storageFiles.end() }); // works
For the case of IIterable<IKeyValuePair<K, V>>, the following alternatives are accepted. Note that some alternatives are available only for synchronous methods.
Alternative | Sync | Async | Notes |
---|---|---|---|
std::map<K, V> const& | Yes | No | |
std::map<K, V>&& | Yes | Yes | Contents are moved into a temporary iterable. |
std::unordered_map<K, V> const& | Yes | No | |
std::unordered_map<K, V>&& | Yes | Yes | Contents are moved into a temporary iterable. |
std::initializer_list<std::pair<K, V>> | Yes | Yes | Async version copies the list into a temporary iterable. |
{ begin, end } |
Yes | No | begin and end must be forward iterators, and begin->first and begin->second must be convertible to K and V, respectively. |
Alternatives for vector view parameters
winrt::param::vector_view<T> and winrt::param::async_vector_view<T> simplify passing parameters as IVectorView<T>.
You can call IVector<T>::GetView to get an IVectorView<T> from an IVector<T>.
In addition to IVectorView<T>, the following alternatives are also accepted. Note that some alternatives are available only for synchronous methods.
Alternative | Sync | Async | Notes |
---|---|---|---|
std::vector<T> const& | Yes | No | |
std::vector<T>&& | Yes | Yes | Contents are moved into a temporary view. |
std::initializer_list<T> | Yes | Yes | Async version copies the list into a temporary view. |
{ begin, end } |
Yes | No | begin and end must be forward iterators, and *begin must be convertible to T. |
Again, the double-iterator version can be used to create vector views out of things that don't fit an existing alternative.
The temporary view is more efficient if the begin
and end
iterators are random-access iterators.
Alternatives for map view parameters
winrt::param::map_view<T> and winrt::param::async_map_view<T> simplify passing parameters as IMapView<T>.
You can call IMap<K, V>::GetView to get an IMapView<K, V> from an IMap<K, V>.
In addition to IMapView<K, V>, the following alternatives are also accepted. Note that some alternatives are available only for synchronous methods.
Alternative | Sync | Async | Notes |
---|---|---|---|
std::map<K, V> const& | Yes | No | |
std::map<K, V>&& | Yes | Yes | Contents are moved into a temporary view. |
std::unordered_map<K, V> const& | Yes | No | |
std::unordered_map<K, V>&& | Yes | Yes | Contents are moved into a temporary view. |
std::initializer_list<std::pair<K, V>> | Yes | Yes | Contents are copied into a temporary view. Keys may not be duplicated. |
Alternatives for vector parameters
winrt::param::vector<T> simplifies passing parameters as IVector<T>. In addition to IVector<T>, these alternatives are also accepted:
Alternative | Notes |
---|---|
std::vector<T>&& | Contents are moved into a temporary vector. Results are not moved back. |
std::initializer_list<T> |
If the method mutates the temporary vector, then those changes are not reflected in the original parameters. To observe the changes, pass an IVector<T>.
Alternatives for map parameters
winrt::param::map<K, V> simplifies passing parameters as IMap<K, V>. In addition to IMap<K, V>, these alternatives are also accepted:
You can pass | Notes |
---|---|
std::map<K, V>&& | Contents are moved into a temporary map. Results are not moved back. |
std::unordered_map<K, V>&& | Contents are moved into a temporary map. Results are not moved back. |
std::initializer_list<std::pair<K, V>> |
If the method mutates the temporary map, then those changes are not reflected in the original parameters. To observe the changes, pass an IMap<K, V>.
Alternatives for array parameters
winrt::array_view<T> is not in the winrt::param namespace, but it is used for parameters that are C-style arrays. In addition to an explicit array_view<T>, these alternatives are also accepted:
Alternative | Notes |
---|---|
{} |
Empty array. |
U[] | A C-style array, where U is convertible to T, and sizeof(U) == sizeof(T) . |
std::array<U, N> | Where U is convertible to T, and sizeof(U) == sizeof(T) . |
std::vector<U> | Where U is convertible to T, and sizeof(U) == sizeof(T) . |
{ begin, end } |
begin and end must be of type T*, representing the range [begin , end ). |
std::initializer_list<T> | |
std::span<U, N> | Where U is convertible to T, and sizeof(U) == sizeof(T) . |
Also see the blog post The various patterns for passing C-style arrays across the Windows Runtime ABI boundary.