對於某些類型,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"sv 和 L"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 |
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>>,以下替代方案被接受。 請注意,有些替代方案僅適用於同步方法。
| 替代方案 | 同步 | 非同步 | 註釋 |
|---|---|---|---|
| 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->first 且和 begin->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> 外,也接受以下替代方案。 請注意,有些替代方案僅適用於同步方法。
| 替代方案 | 同步 | 非同步 | 註釋 |
|---|---|---|---|
| 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。 |
同樣地,雙迭代版本可以用來從不符合現有替代方案的事物中建立向量視圖。
如果 begin 和 end 迭代器是隨機存取迭代器,臨時視圖會更有效率。
地圖檢視參數的替代方案
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 } |
begin 且 end 必須屬於 T*,代表範圍 [begin, end)。 |
| std::initializer_list<T> | |
| std::span<U, N> | 其中 U 可轉換為 T,且 sizeof(U) == sizeof(T)。 |
另請參閱部落格文章《跨越 Windows 執行階段 ABI 邊界傳遞 C 風格陣列的各種模式》。