將參數傳遞至預測 API

對於某些類型,C++/WinRT 提供將參數傳遞給投影 API 的替代方法。 這些參數接受類別被置於 winrt::p aram 命名空間中。 只有 C++/WinRT 生成的程式碼才應該使用這些類別;不要在自己的函式和方法中使用它們。

這很重要

你不應自行使用 winrt::param 命名空間中的型別。 這是為了讓投影效果更好。

其中一些替代方案區分了同步呼叫與非同步呼叫。 非同步呼叫的版本通常會取得參數資料的所有權,以確保值在非同步呼叫完成前保持有效且不變。 但請注意,此保護並不延伸至其他執行緒對該集合所做的變更。 防止這種情況是你的責任。

字串參數的替代方案

winrt::param::hstring 可簡化將參數作為 winrt::hstring 傳遞。 除了 winrt::hstring 外,以下替代方案也被接受:

替代方案 註釋
{} 空字串。
std::wstring_view 視圖後方必須有一個零終止子。
STD::wstring
wchar_t const* 一個空終端字串。

你無法傳遞 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> 外,也接受以下替代方案。 請注意,有些替代方案僅適用於同步方法。

替代方案 同步 非同步 註釋
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 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>>,以下替代方案被接受。 請注意,有些替代方案僅適用於同步方法。

替代方案 同步 非同步 註釋
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 beginend 必須是 前向迭代器begin->first 且和 begin->second 必須分別可轉換為 KV

向量視圖參數的替代方案

winrt::param::vector_view<T>winrt::param::async_vector_view<T> 簡化了以 IVectorView<T> 傳遞參數。

你可以呼叫 IVector<T>::GetView,從 IVector<T> 取得 IVectorView<T>

除了 IVectorView<T> 外,也接受以下替代方案。 請注意,有些替代方案僅適用於同步方法。

替代方案 同步 非同步 註釋
std::vector<T> const& Yes No
std::vector<T>&& Yes Yes 內容已移至暫存檢視畫面。
std::initializer_list<T> Yes Yes 非同步版本會將清單複製到暫時檢視中。
{ begin, end } Yes No 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> 外,以下替代方案也被接受。 請注意,有些替代方案僅適用於同步方法。

替代方案 同步 非同步 註釋
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>外,以下替代方案也被接受:

替代方案 註釋
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::p aram 命名空間中,但它用於 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*,代表範圍 [beginend)。
std::initializer_list<T>
std::span<U, N> 其中 U 可轉換為 T,且 sizeof(U) == sizeof(T)

另請參閱部落格文章《跨越 Windows 執行階段 ABI 邊界傳遞 C 風格陣列的各種模式》。