将参数传递给计划中的 API

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

Important

不应自行使用 winrt::param 命名空间中的类型。 这是为了提升投影效果。

其中一些替代方法区分同步调用和异步调用。 异步调用的版本通常获取参数数据的所有权,以确保值在异步调用完成之前保持有效且保持不变。 但是,请注意,这种保护并不适用于来自另一个线程对该集合所做的更改。 防止这是你的责任。

字符串参数的替代项

winrt::param::hstring 简化了以 winrt::hstring 形式传递参数。 除了 winrt::hstring 之外,还接受以下替代项:

备选方案 Notes
{} 空字符串。
std::wstring_view 该视图后面必须有一个空终止符。
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>,以下替代项也同样可接受。 请注意,某些替代方法仅适用于同步方法。

备选方案 同步 异步 Notes
std::vector<T> const& Yes No
std::vector<T>&& Yes Yes 内容将移入临时可迭代对象中。
std::initializer_list<T> Yes Yes 异步版本会复制这些项。
std::initializer_list<U> Yes No U 必须可转换为 T
{ begin, end } Yes No begin 并且 end 必须是 向前迭代器,并且 *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>> 的情况,接受以下替代方法。 请注意,某些替代方法仅适用于同步方法。

备选方案 同步 异步 Notes
std::map<K,V> const& Yes No
std::map<K, V>&& Yes Yes 内容被移入一个临时可迭代对象中。
std::unordered_map<K、V> const& Yes No
std::unordered_map<K、V>&& Yes Yes 内容将被移入临时可迭代对象中。
std::initializer_list<std::pair<K, V>> Yes Yes 异步版本将列表复制到一个临时的可迭代对象中。
{ begin, end } Yes No begin并且end必须是向前迭代器,并且begin->firstbegin->second必须分别转换为 KV

矢量视图参数的替代项

winrt::param::vector_view<T>winrt::param::async_vector_view<T> 简化了将参数作为 IVectorView<T> 传递。

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

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

备选方案 同步 异步 Notes
std::vector<T> const& Yes No
std::vector<T>&& Yes Yes 内容已移至临时视图中。
std::initializer_list<T> Yes Yes 异步版本将列表复制到临时视图中。
{ begin, end } Yes No begin 并且 end 必须是 向前迭代器,并且 *begin 必须可转换为 T

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

地图视图参数的替代方法

winrt::param::map_view<T>winrt::param::async_map_view<T> 简化了将参数作为 IMapView<T> 传递。

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

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

备选方案 同步 异步 Notes
std::map<K,V> const& Yes No
std::map<K, V>&& Yes Yes 内容已移至临时视图中。
std::unordered_map<K、V> const& Yes No
std::unordered_map<K、V>&& Yes Yes 内容将移动到临时视图中。
std::initializer_list<std::pair<K, V>> Yes Yes 内容将复制到临时视图中。 密钥可能不重复。

矢量参数的替代项

winrt::param::vector<T> 简化了以 IVector<T> 形式传递参数。 除了 IVector<T> 之外,还接受以下替代方法:

备选方案 Notes
std::vector<T>&& 内容将移动到临时向量中。 结果不会移回原处。
std::initializer_list<T>

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

映射参数的替代方法

winrt::param::map<K, V> 简化了将参数作为 IMap<K, V> 进行传递。 除了 IMap<K、V> 之外,还接受以下替代项:

你可以传递 Notes
std::map<K, V>&& 内容被移入临时映射中。 结果不会移回原处。
std::unordered_map<K、V>&& 内容将移动到临时映射中。 结果 不会 移回。
std::initializer_list<std::pair<K, V>>

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

数组参数的替代项

winrt::array_view<T> 不在 winrt::p aram 命名空间中,但它用于 C 样式数组的参数。 除了显式 array_view<T> 之外,还接受以下替代方法:

备选方案 Notes
{} 空数组。
U[] C 样式数组,其中 U 可转换为 Tsizeof(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 样式数组的各种模式