標準的な C++ のデータ型と C++/WinRT

C++/WinRT では、標準的な C++ データ型 (いくつかの C++ 標準ライブラリのデータ型を含む) を使用して Windows ランタイム API を呼び出すことができます。 API に標準文字列を渡すことができるほか (「C++/WinRT での文字列の処理」を参照)、意味的に等価なコレクションを期待する API に初期化リストと標準コンテナーを渡すこともできます。

また、「ABI 境界へのパラメーターの受け渡し」もご覧ください。

標準初期化子リスト

初期化子リスト (std::initializer_list) は C++ 標準ライブラリ コンストラクトです。 初期化子リストは、特定の Windows ランタイム コンストラクターとメソッドを呼び出すときに使用できます。 たとえば、いずれかを使用して DataWriter::WriteBytes を呼び出すことができます。

#include <winrt/Windows.Storage.Streams.h>

using namespace winrt::Windows::Storage::Streams;

int main()
{
    winrt::init_apartment();

    InMemoryRandomAccessStream stream;
    DataWriter dataWriter{stream};
    dataWriter.WriteBytes({ 99, 98, 97 }); // the initializer list is converted to a winrt::array_view before being passed to WriteBytes.
}

これを機能させるには、2つの要素が関わります。 まず、DataWriter::WriteBytes メソッドが winrt::array_view 型のパラメーターを受け取ります。

void WriteBytes(winrt::array_view<uint8_t const> value) const

winrt::array_view は C++/WinRT のカスタム型であり、連続した一連の値を安全に表します (C++/WinRT 基本ライブラリ、%WindowsSdkDir%Include\<WindowsTargetPlatformVersion>\cppwinrt\winrt\base.h で定義されています)。

2 番目に、winrt::array_view は初期化子リスト コンストラクターを持っています。

template <typename T> winrt::array_view(std::initializer_list<T> value) noexcept

多くの場合、プログラミングで winrt::array_view を認識するかどうかを選択できます。 これを認識しないことを選択する場合、対応する型が C++ 標準ライブラリに現れた場合に変更すべきコードはありません。

初期化子リストは、コレクション パラメーターを必要とする Windows ランタイム API に渡すことができます。 StorageItemContentProperties::RetrievePropertiesAsync を例として説明します。

IAsyncOperation<IMap<winrt::hstring, IInspectable>> StorageItemContentProperties::RetrievePropertiesAsync(IIterable<winrt::hstring> propertiesToRetrieve) const;

このような初期化子リストを使用して、その API を呼び出すことができます。

IAsyncAction retrieve_properties_async(StorageFile const storageFile)
{
    auto properties{ co_await storageFile.Properties().RetrievePropertiesAsync({ L"System.ItemUrl" }) };
}

ここでは、2 つの要因が働きます。 最初に、呼び出し先が初期化子リストから std::vector を作成します (この呼び出し先は非同期であるため、そのオブジェクトを所有することができます。これは必須です)。 次に、C++/WinRT は std::vector を Windows ランタイム コレクション パラメーターとして透過的に (コピーを導入せずに) バインドします。

標準の配列とベクター

winrt::array_view は、std::vector および std::array からの変換コンストラクターも持っています。

template <typename C, size_type N> winrt::array_view(std::array<C, N>& value) noexcept
template <typename C> winrt::array_view(std::vector<C>& vectorValue) noexcept

したがって、代わりに std::vector を使用して DataWriter::WriteBytes を呼び出すことができます。

std::vector<byte> theVector{ 99, 98, 97 };
dataWriter.WriteBytes(theVector); // theVector is converted to a winrt::array_view before being passed to WriteBytes.

または、std::array を使用します。

std::array<byte, 3> theArray{ 99, 98, 97 };
dataWriter.WriteBytes(theArray); // theArray is converted to a winrt::array_view before being passed to WriteBytes.

C++/WinRT は、std::vector を Windows ランタイム コレクション パラメーターとしてバインドします。 したがって、std::vector<winrt::hstring> を渡すことができます。この結果、これは winrt::hstring の適切な Windows ランタイム コレクション変換されます。 呼び出し先が非同期である場合に留意する必要がある追加の詳細があります。 その場合の実装の詳細により、rvalue 値を指定する必要があるので、ベクトルのコピーまたは移動を実現する必要があります。 以下のコード例では、非同期呼び出し先によって受け入れられたパラメーター型のオブジェクトにベクトルの所有権を移動します (そして、移動後に vecH に再びアクセスしないように注意します)。 rvalue の詳細については、「値のカテゴリ、およびそれらへの参照」を参照してください。

IAsyncAction retrieve_properties_async(StorageFile const storageFile, std::vector<winrt::hstring> vecH)
{
	auto properties{ co_await storageFile.Properties().RetrievePropertiesAsync(std::move(vecH)) };
}

ただし、windows ランタイム コレクションが求める std::vector<std::wstring> を渡すことはできません。 なぜなら、std::wstring の適切な Windows ランタイム コレクションに変換された場合、C++ 言語はそのコレクションの型パラメーターを強制しないためです。 結果として、次のコード例はコンパイルされません (解決策は、上記のように、std::vector<winrt::hstring> を代わりに渡すことです)。

IAsyncAction retrieve_properties_async(StorageFile const storageFile, std::vector<std::wstring> vecW)
{
    auto properties{ co_await storageFile.Properties().RetrievePropertiesAsync(std::move(vecW)) }; // error! Can't convert from vector of wstring to async_iterable of hstring.
}

生の配列とポインターの範囲

将来の C++ 標準ライブラリで対応する型が存在する可能性があることに注意して、選択する場合、または必要に応じて、winrt::array_view を直接操作することもできます。

winrt::array_view は、未加工配列およびさまざまな T* (要素型へのポインター) からの変換コンストラクターを持っています。

using namespace winrt;
...
byte theRawArray[]{ 99, 98, 97 };
array_view<byte const> fromRawArray{ theRawArray };
dataWriter.WriteBytes(fromRawArray); // the winrt::array_view is passed to WriteBytes.

array_view<byte const> fromRange{ theArray.data(), theArray.data() + 2 }; // just the first two elements.
dataWriter.WriteBytes(fromRange); // the winrt::array_view is passed to WriteBytes.

winrt::array_view の関数と演算子

コンストラクター、演算子、関数、および反復子のホストが winrt::array_view に対して実装されています。 winrt::array_view は範囲であるため、範囲ベースの for、または std::for_each で使用できます。

詳細な例と情報については、winrt::array_view API リファレンス トピックを参照してください。

IVector<T> と標準的な反復コンストラクト

SyndicationFeed.Items は、IVector<T> 型のコレクション (winrt::Windows::Foundation::Collections::IVector<T> として C++/WinRT に投影される) を返す Windows ランタイム API の例です。 この型は、範囲ベースの for など、標準的な反復コンストラクトで使用できます。

// main.cpp
#include "pch.h"
#include <winrt/Windows.Web.Syndication.h>
#include <iostream>

using namespace winrt;
using namespace Windows::Web::Syndication;

void PrintFeed(SyndicationFeed const& syndicationFeed)
{
    for (SyndicationItem const& syndicationItem : syndicationFeed.Items())
    {
        std::wcout << syndicationItem.Title().Text().c_str() << std::endl;
    }
}

非同期 Windows ランタイム API を使用した C++ コルーチン

非同期 Windows ランタイム API を呼び出すときには、引き続き並列パターン ライブラリ (PPL) を使用できます。 しかし、多くの場合、C++ コルーチンは非同期オブジェクトとのやりとり用に、効率的でコーディングがより簡単なイディオムを提供します。 詳細とコード例については、「C++/WinRT を使用した同時開催操作と非同期操作」を参照してください。

重要な API