将参数传递给投影 API

对于某些类型,C++/WinRT 提供了将参数传递到投影 API 的替代方法。 这些接受参数的类放置在 winrt::param 命名空间中。 仅 C++/WinRT 生成的代码应使用这些类;请勿在自己的函数和方法中使用它们。

重要

不应自行使用 winrt::param 命名空间中的类型。 它们的用途是为投影提供帮助。

其中一些替代项区分同步调用和异步调用。 异步调用的版本通常获取参数数据的所有权,以确保值在异步调用完成之前保持有效且保持不变。 但注意,此保护不会扩展到从另一个线程对集合的更改。 防止从另一个线程中转变集合是你的责任。

字符串参数的替代项

winrt::param::hstring 简化了将参数作为 winrt::hstring 传递的过程。 除了 winrt::hstring,还接受以下替代项

替代项 说明
{} 空字符串。
std::wstring_view 视图必须后跟 null 终止符。
std::wstring
wchar_t const* 以 null 终止的字符串。

无法传递 nullptr 来表示空字符串。 请改为使用 L""{}

编译器知道在编译时如何评估字符串文本上的 wcslen。 因此,对于文本,L"Name"svL"Name" 是等效的。

请注意,std::wstring_view 对象不以 null 终止,但 C++/WinRT 要求视图末尾后的字符为 null。 如果你传递并非以 null 终止的 std::wstring_view,则过程将会终止。

可迭代参数的替代方法

winrt::param::iterable<T> 和 winrt::param::async_iterable<T> 简化了将参数作为 IIterable<T> 传递的过程

Windows 运行时集合 IVector<T> 和 IVectorView<T> 已支持 IIterable<T>。 Windows 运行时集合 IMap<K, V> 和 IMapView<K, V> 已支持 IIterable<IKeyValuePair<K, V>>

除了 IIterable<T>,还接受以下替代项。 请注意,某些替代项仅适用于同步方法。

替代项 同步 Async 备注
std::vector<T> const&
std::vector<T>&& 内容将移动到临时可迭代对象中。
std::initializer_list<T> 异步版本复制这些项。
std::initializer_list<U> U必须可转换为 T
{ begin, end } beginend 必须为前向迭代器,且 *begin 必须可转换为 T

双迭代器更普遍适用于你有一个不适合以上任何方案的集合的情况,只要你可以循环访问它并生成可以转换为 T 的内容。例如,你可能具有 IVector<U> 或 std::vector<U>,其中 U 可转换为 T

在以下示例中,SetStorageItems 方法需要 IIterable<IStorageItem>。 使用双迭代器模式,可以传递其他类型的集合。

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

对于 IIterable<IKeyValuePair<K, V>>,接受以下替代项。 请注意,某些替代项仅适用于同步方法。

替代项 同步 Async 备注
std::map<K, V> const&
std::map<K, V>&& 内容将移动到临时可迭代对象中。
std::unordered_map<K, V> const&
std::unordered_map<K, V>&& 内容将移动到临时可迭代对象中。
std::initializer_list<std::pair<K, V>> 异步版本将列表复制到临时可迭代对象中。
{ begin, end } beginend 必须为前向迭代器,且 begin->firstbegin->second 必须分别可转换为 K 和 V

矢量视图参数的替代项

winrt::param::vector_view<T> 和 winrt::param::async_vector_view<T> 简化了将参数作为 IVectorView<T> 传递的过程

可以调用 IVector<T>::GetView 从 IVector<T> 获取 IVectorView<T>

除了 IVectorView<T>,还接受以下替代项。 请注意,某些替代项仅适用于同步方法。

替代项 同步 Async 备注
std::vector<T> const&
std::vector<T>&& 内容将移动到临时视图中。
std::initializer_list<T> 异步版本将列表复制到临时视图中。
{ begin, end } beginend 必须为前向迭代器,且 *begin 必须可转换为 T

同样,双迭代器版本可用于从那些不适合现有替代项的内容创建矢量视图。 如果 beginend 迭代器是随机访问迭代器,则临时视图更高效。

映射视图参数的替代项

winrt::param::map_view<T> 和 winrt::param::async_map_view<T> 简化了将参数作为 IMapView<T> 传递的过程

可以调用 IMap<K, V>::GetView,从 IMap<K, V> 获取 IMapView<K, V>

除了 IMapView<K, V>,还接受以下替代项。 请注意,某些替代项仅适用于同步方法。

替代项 同步 Async 备注
std::map<K, V> const&
std::map<K, V>&& 内容将移动到临时视图中。
std::unordered_map<K, V> const&
std::unordered_map<K, V>&& 内容将移动到临时视图中。
std::initializer_list<std::pair<K, V>> 内容将复制到临时视图中。 键不能重复。

矢量参数的替代项

winrt::param::vector<T> 简化了将参数作为 IVector<T> 传递的过程。 除了 IVector<T>,还接受以下替代项

替代项 备注
std::vector<T>&& 内容将移动到临时矢量中。 结果不会移回
std::initializer_list<T>

如果该方法改变了临时矢量,则这些更改不会反映在原始参数中。 若要观察更改,请传递 IVector<T>

映射参数的替代项

winrt::param::map<K, V> 简化了将参数作为 IMap<K, V> 传递的过程。 除了 IMap<K, V>,还接受以下替代项

可以传递 备注
std::map<K, V>&& 内容将移动到临时映射中。 结果会移回。
std::unordered_map<K, V>&& 内容将移动到临时映射中。 结果不会移回
std::initializer_list<std::pair<K, V>>

如果该方法改变了临时映射,则这些更改不会反映在原始参数中。 若要观察更改,请传递 IMap<K, V>

数组参数的替代项

winrt::array_view<T> 不在 winrt::param 命名空间中,但对于作为 C 样式数组的参数,可以使用它。 除了显式 array_view<T>,还接受以下替代项

替代项 说明
{} 空数组。
U[] C 样式数组,其中 U 可转换为 T,且 sizeof(U) == sizeof(T)
std::array<U, N> 其中 U 可转换为 T,且 sizeof(U) == sizeof(T)
std::vector<U> 其中 U 可转换为 T,且 sizeof(U) == sizeof(T)
{ begin, end } beginend 的类型必须为 T*,表示范围 [begin, end]
std::initializer_list<T>
std::span<U, N> 其中 U 可转换为 T,且 sizeof(U) == sizeof(T)

另请参阅博客文章跨 Windows 运行时 ABI 边界传递 C 样式数组的多种模式