C++/WinRT の新機能What's new in C++/WinRT

C++/WinRT 2.0 の新機能と変更点News, and changes, in C++/WinRT 2.0

C++/WinRT Visual Studio Extension (VSIX)Microsoft.Windows.CppWinRT NuGet パッケージcppwinrt.exe ツールの入手やインストール方法などの詳細については、「Visual Studio のサポートの C +/cli WinRT、XAML、VSIX 拡張機能と NuGet パッケージ」を参照してください。For more info about the C++/WinRT Visual Studio Extension (VSIX), the Microsoft.Windows.CppWinRT NuGet package, and the the cppwinrt.exe tool—including how to acquire and install them—see Visual Studio support for C++/WinRT, XAML, the VSIX extension, and the NuGet package.

バージョン 2.0 の C++/WinRT Visual Studio Extension (VSIX) の変更点Changes to the C++/WinRT Visual Studio Extension (VSIX) for version 2.0

  • デバッグ ビジュアライザーは、引き続き Visual Studio 2017 をサポートするのに加えて、Visual Studio 2019 をサポートするようになります。The debug visualizer now supports Visual Studio 2019; as well as continuing to support Visual Studio 2017.
  • 多くのバグ修正が行われました。Numerous bug fixes have been made.

バージョン 2.0 の Microsoft.Windows.CppWinRT NuGet パッケージの変更点Changes to the Microsoft.Windows.CppWinRT NuGet package for version 2.0

  • 必要に応じてプロジェクトごとにプラットフォーム プロジェクション ヘッダーを生成する cppwinrt.exe ツールは、Microsoft.Windows.CppWinRT NuGet パッケージに含まれるようになります。The cppwinrt.exe tool is now included in the Microsoft.Windows.CppWinRT NuGet package, and the tool generates platfom projection headers for each project on demand. その結果、cppwinrt.exe ツールは Windows SDK に依存しなくなります (ただし、互換性の理由から、ツールには引き続き SDK が付属しています)。Consequently, the cppwinrt.exe tool no longer depends on the Windows SDK (although, the tool still ships with the SDK for compatibility reasons).
  • 並列ビルドを有効にするため、cppwinrt.exe では各プラットフォーム/構成固有の中間フォルダー ($IntDir) の下に、プロジェクション ヘッダーが生成されるようになりました。cppwinrt.exe now generates projection headers under each platform/configuration-specific intermediate folder ($IntDir) to enable parallel builds.
  • プロジェクト ファイルを手動でカスタマイズする場合のため、C++/WinRT のビルドのサポート (プロパティ/ターゲット) が完全にドキュメント化されるようになりました。The C++/WinRT build support (props/targets) is now fully documented, in case you want to manually customize your project files. Microsoft.Windows.CppWinRT NuGet Package」(Microsoft.Windows.CppWinRT NuGet パッケージ) をご覧ください。See Microsoft.Windows.CppWinRT NuGet Package.
  • 多くのバグ修正が行われました。Numerous bug fixes have been made.

バージョン 2.0 での C++/WinRT の変更点Changes to C++/WinRT for version 2.0

オープン ソースOpen source

cppwinrt.exe ツールでは、Windows ランタイム メタデータ (.winmd) ファイルが取得され、それに基づいて、メタデータで記述されている API を "プロジェクト" するヘッダー ファイル ベースの標準 C++ ライブラリが生成されます。The cppwinrt.exe tool takes a Windows Runtime metadata (.winmd) file, and generates from it a header-file-based standard C++ library that projects the APIs described in the metadata. それにより、C++/WinRT のコードからそれらの API を使用できます。That way, you can consume those APIs from your C++/WinRT code.

このツールは完全なオープン ソース プロジェクトになり、GitHub で入手できます。This tool is now an entirely open source project, available on GitHub. Microsoft/xlang に移動し、src > tool > cppwinrt の順にクリックします。Visit Microsoft/xlang, and then click in to src > tool > cppwinrt.

xlang ライブラリxlang libraries

完全に移植可能なヘッダーのみのライブラリ (Windows ランタイムで使用される ECMA-335 メタデータ形式の解析用) により、今後のすべての Windows ランタイムおよび xlang ツールの基礎が形成されます。A completely portable header-only library (for parsing the ECMA-335 metadata format used by the Windows Runtime) forms the basis of all the Windows Runtime and xlang tooling going forward. 特に、cppwinrt.exe ツールは xlang ライブラリを使ってまったく新しく書き直しました。Notably, we also rewrote the cppwinrt.exe tool from the ground up using the xlang libraries. これにより、メタデータのより正確なクエリが提供されるようになり、C++/WinRT 言語プロジェクションに関する長期にわたるいくつかの問題が解決されます。This provides far more accurate metadata queries, solving a few long-standing issues with the C++/WinRT language projection.

依存関係の数の削減Fewer dependencies

xlang メタデータ リーダーにより、cppwinrt.exe ツール自体の依存関係の数が少なくなります。Due to the xlang metadata reader, the cppwinrt.exe tool itself has fewer dependencies. これにより、柔軟性が増し、より多くのシナリオ (特に、制限の厳しいビルド環境) で使用できるようになります。This makes it far more flexible, as well as being usable in more scenarios—especially in constrained build environments. 特に、RoMetadata.dll に依存しなくなります。Notably, it no longer relies on RoMetadata.dll.   cppwinrt.exe 2.0 での依存関係は次のとおりです。These are the dependencies for cppwinrt.exe 2.0.  

  • api-ms-win-core-processenvironment-l1-1-0.dllapi-ms-win-core-processenvironment-l1-1-0.dll
  • api-ms-win-core-libraryloader-l1-2-0.dllapi-ms-win-core-libraryloader-l1-2-0.dll
  • XmlLite.dllXmlLite.dll
  • api-ms-win-core-memory-l1-1-0.dllapi-ms-win-core-memory-l1-1-0.dll
  • api-ms-win-core-handle-l1-1-0.dllapi-ms-win-core-handle-l1-1-0.dll
  • api-ms-win-core-file-l1-1-0.dllapi-ms-win-core-file-l1-1-0.dll
  • SHLWAPI.dllSHLWAPI.dll
  • ADVAPI32.dllADVAPI32.dll
  • KERNEL32.dllKERNEL32.dll
  • api-ms-win-core-rtlsupport-l1-1-0.dllapi-ms-win-core-rtlsupport-l1-1-0.dll
  • api-ms-win-core-processthreads-l1-1-0.dllapi-ms-win-core-processthreads-l1-1-0.dll
  • api-ms-win-core-heap-l1-1-0.dllapi-ms-win-core-heap-l1-1-0.dll
  • api-ms-win-core-console-l1-1-0.dllapi-ms-win-core-console-l1-1-0.dll
  • api-ms-win-core-localization-l1-2-0.dllapi-ms-win-core-localization-l1-2-0.dll

これらの依存関係とは対照的に、cppwinrt.exe 1.0 では次のとおりです。Contrasting with these dependencies, which cppwinrt.exe 1.0 has.

  • ADVAPI32.dllADVAPI32.dll
  • SHELL32.dllSHELL32.dll
  • api-ms-win-core-file-l1-1-0.dllapi-ms-win-core-file-l1-1-0.dll
  • XmlLite.dllXmlLite.dll
  • api-ms-win-core-libraryloader-l1-2-0.dllapi-ms-win-core-libraryloader-l1-2-0.dll
  • api-ms-win-core-processenvironment-l1-1-0.dllapi-ms-win-core-processenvironment-l1-1-0.dll
  • RoMetadata.dllRoMetadata.dll
  • SHLWAPI.dllSHLWAPI.dll
  • KERNEL32.dllKERNEL32.dll
  • api-ms-win-core-rtlsupport-l1-1-0.dllapi-ms-win-core-rtlsupport-l1-1-0.dll
  • api-ms-win-core-heap-l1-1-0.dllapi-ms-win-core-heap-l1-1-0.dll
  • api-ms-win-core-timezone-l1-1-0.dllapi-ms-win-core-timezone-l1-1-0.dll
  • api-ms-win-core-console-l1-1-0.dllapi-ms-win-core-console-l1-1-0.dll
  • api-ms-win-core-localization-l1-2-0.dllapi-ms-win-core-localization-l1-2-0.dll
  • OLEAUT32.dllOLEAUT32.dll
  • api-ms-win-core-winrt-error-l1-1-0.dllapi-ms-win-core-winrt-error-l1-1-0.dll
  • api-ms-win-core-winrt-error-l1-1-1.dllapi-ms-win-core-winrt-error-l1-1-1.dll
  • api-ms-win-core-winrt-l1-1-0.dllapi-ms-win-core-winrt-l1-1-0.dll
  • api-ms-win-core-winrt-string-l1-1-0.dllapi-ms-win-core-winrt-string-l1-1-0.dll
  • api-ms-win-core-synch-l1-1-0.dllapi-ms-win-core-synch-l1-1-0.dll
  • api-ms-win-core-threadpool-l1-2-0.dllapi-ms-win-core-threadpool-l1-2-0.dll
  • api-ms-win-core-com-l1-1-0.dllapi-ms-win-core-com-l1-1-0.dll
  • api-ms-win-core-com-l1-1-1.dllapi-ms-win-core-com-l1-1-1.dll
  • api-ms-win-core-synch-l1-2-0.dllapi-ms-win-core-synch-l1-2-0.dll 

Windows ランタイムの noexcept 属性The Windows Runtime noexcept attribute

Windows ランタイムの新しい [noexcept] 属性を使うと、MIDL 3.0 のメソッドとプロパティを修飾することができます。The Windows Runtime has a new [noexcept] attribute, which you may use to decorate your methods and properties in MIDL 3.0. この属性が存在すると、実装で例外がスローされない (エラー HRESULT も返されない) ことをサポート ツールに示します。The presence of the attribute indicates to supporting tools that your implementation doesn't throw an exception (nor return a failing HRESULT). これにより、言語プロジェクションでは、失敗する可能性のあるアプリケーション バイナリ インターフェイス (ABI) の呼び出しをサポートするために必要な例外処理のオーバーヘッドを回避することで、コードの生成を最適化することができます。This allows language projections to optimize code-generation by avoiding the exception-handling overhead that's required to support application binary interface (ABI) calls that can potentially fail.

C++/WinRT では、使用コードと作成コード両方の C++ noexcept の実装を生成することによって、これを利用します。C++/WinRT takes advantage of this by producing C++ noexcept implementations of both the consuming and authoring code. エラーが発生しない API のメソッドまたはプロパティがあり、コードのサイズを考慮することが必要な場合は、この属性を検討できます。If you have API methods or properties that are fail-free, and you're concerned about code size, then you can investigate this attribute.

最適化されたコード生成Optimized code-generation

C++ コンパイラで可能な限り小さくて効率的なバイナリ コードを生成できるよう、C++/WinRT ではいっそう効率的な C++ ソース コードが (バックグラウンドで) 生成されるようになります。C++/WinRT now generates even more efficient C++ source code (behind the scenes) so that the C++ compiler can produce the smallest and most efficient binary code possible. 不要なアンワインド情報を回避することで、例外処理のコストの削減を目的とする多くの機能強化が行われています。Many of the improvements are geared toward reducing the cost of exception-handling by avoiding unnecessary unwind information. 大量の C++WinRT コードを使うバイナリでは、コードのサイズが約 4% 削減されます。Binaries that use large amounts of C++/WinRT code will see roughly a 4% reduction in code size. また、命令の数が減るため、コードがいっそう効率的に (より速く実行されるように) なります。The code is also more efficient (it runs faster) due to the reduced instruction count.

これらの機能強化は、使用可能な新しい相互運用機能にも依存します。These improvements rely on a new interop feature that's available to you, as well. リソース所有者であるすべての C++/WinRT 型には、前の 2 つのステップのアプローチを回避し、所有権を直接取得するためのコンストラクターが含まれます。All of the C++/WinRT types that are resource owners now include a constructor for taking ownership directly, avoiding the previous two-step approach.

ABI::Windows::Foundation::IStringable* raw = ...

IStringable projected(raw, take_ownership_from_abi);

printf("%ls\n", projected.ToString().c_str());

最適化された例外処理 (EH) コード生成Optimized exception-handling (EH) code-generation

この変更は、Microsoft C++ オプティマイザー チームによって行われた作業を補完して、例外処理のコストを削減します。This change complements work that has been done by the Microsoft C++ optimizer team to reduce the cost of exception-handling. アプリケーション バイナリ インターフェイス (ABI) (COM など) をコード内で大量に使う場合、このパターンに従うコードを多く目にします。If you use application binary interfaces (ABIs) (such as COM) heavily in your code, then you'll observe a lot of code following this pattern.

int32_t Function() noexcept
{
    try
    {
        // code here constitutes unique value.
    }
    catch (...)
    {
        // code here is always duplicated.
    }
}

C++/WinRT 自体では、実装されているすべての API に対してこのパターンが生成されます。C++/WinRT itself generates this pattern for every API that's implemented. 何千もの API 関数において、ここでの最適化が重要である可能性があります。With thousands of API functions, any optimization here can be significant. これまで、オプティマイザーではそれらの catch ブロックがすべて同じであることは検出されなかったため、各 ABI で多くのコードが重複していました (それは、システム コードで例外を使うと大きなバイナリが生成されるという確信の原因になっていました)。In the past, the optimizer wouldn't detect that those catch blocks are all identical, so it was duplicating a lot of code around each ABI (which in turn contributed to the belief that using exceptions in system code produces large binaries). しかし、Visual Studio 2019 以降の C++ コンパイラでは、それらのすべての catch funclet が折りたたまれていて、固有のものだけが格納されます。However, from Visual Studio 2019 on, the C++ compiler folds all of those catch funclets, and only stores those that are unique. 結果として、このパターンに大きく依存するバイナリのコード サイズは全体的としてさらに 18% 減少します。The result is a further and overall 18% reduction in code size for binaries that rely heavily on this pattern. EH コードがリターン コードを使うより効率的になっただけでなく、大きいバイナリ ファイルに関する心配は過去のものになりました。Not only is EH code now more efficient than using return codes, but also the concern about larger binaries is now a thing of the past.

インクリメンタル ビルドの機能強化Incremental build improvements

cppwinrt.exe ツールでは、生成されたヘッダー/ソース ファイルの出力がディスク上の既存のファイルの内容と比較されて、ファイルが実際に変更されている場合にのみ、ファイルが書き込まれます。The cppwinrt.exe tool now compares the output of a generated header/source file against the contents of any existing file on disk, and it only writes out the file if the file has in fact changed. これにより、ディスク I/O の時間がかなり短縮され、C++ コンパイラによってファイルが "ダーティ" と見なされないことが保証されます。This saves considerable time with disk I/O, and it ensures that the files are not considered "dirty" by the C++ compiler. 結果として、多くの場合に、再コンパイルが回避または縮小されます。The result is that recompilation is avoided, or reduced, in many cases.

ジェネリック インターフェイスがすべて生成されるようになったGeneric interfaces are now all generated

xlang メタデータ リーダーのため、C++/WinRT では、すべてのパラメーター化された、またはジェネリック インターフェイスがメタデータから生成されるようになりました。Due to the xlang metadata reader, C++/WinRT now generates all parameterized, or generic, interfaces from metadata. Windows::Foundation::Collections::IVector<T> などのインターフェイスは、winrt/base.h の手書きからではなく、メタデータから生成されるようになります。Interfaces such as Windows::Foundation::Collections::IVector<T> are now generated from metadata rather than hand-written in winrt/base.h. その結果、winrt/base.h のサイズが半分になり、最適化がコードですぐに生成されます (手書きのアプローチではこれを行うのは大変でした)。The result is that the size of winrt/base.h has been cut in half, and that optimizations are generated right into the code (which was tricky to do with the hand-rolled approach).

重要

示されている例のようなインターフェイスは、winrt/base.h ではなく、それぞれの名前空間のヘッダーに存在するようになります。Interfaces such as the example given now appear in their respective namespace headers, rather than in winrt/base.h. そのため、まだそのようにしていない場合、インターフェイスを使うには、適切な名前空間のヘッダーをインクルードする必要があります。So, if you have not already done so, you'll have to include the appropriate namespace header in order to use the interface.

コンポーネントの最適化Component optimizations

この更新では、以下のセクションで説明するように、C++/WinRT に対して複数の追加オプトイン最適化のサポートが追加されています。This update adds support for several additional opt-in optimizations for C++/WinRT, described in the sections below. これらの最適化は破壊的変更なので (サポートするために小さな変更を行う必要があります)、明示的に有効にする必要があります。Because these optimizations are breaking changes (which you may need to make minor changes to support), you'll need to turn them on explicitly. Visual Studio で、プロジェクトのプロパティ [共通プロパティ] > [C++/WinRT] > [最適化][はい] に設定します。In Visual Studio, set project property Common Properties > C++/WinRT > Optimized to Yes. その効果として、プロジェクト ファイルに <CppWinRTOptimized>true</CppWinRTOptimized> が追加されます。That has the effect of adding <CppWinRTOptimized>true</CppWinRTOptimized> to your project file. また、コマンド ラインから cppwinrt.exe を呼び出すときに -opt[imize] スイッチを追加するのと同じ効果があります。And it has the same effect as adding the -opt[imize] switch when invoking cppwinrt.exe from the command line.

(プロジェクト テンプレートからの) 新しいプロジェクトでは、-opt が既定で使われます。A new project (from a project template) will use -opt by default.

均一コンストラクション、実装への直接アクセスUniform construction, and direct implementation access

これら 2 つの最適化により、コンポーネントでは、プロジェクションが実行された型のみを使う場合であっても、独自の実装型に直接アクセスできます。These two optimizations allow your component direct access to its own implementation types, even when it's only using the projected types. パブリック API サーフェスを使うだけの場合は、makemake_selfget_self を使う必要はありません。There's no need to use make, make_self, nor get_self if you simply want to use the public API surface. 呼び出しは実装の直接呼び出しにコンパイルされ、完全にインライン化される可能性さえあります。Your calls will compile down to direct calls into the implementation, and those might even be entirely inlined. 均一の構築について詳しくは、FAQ の「"クラスが登録されていません" という例外が発生するのはなぜですか?」をご覧ください。For more info about uniform construction, see the FAQ Why am I getting a "class not registered" exception?.

型消去されたファクトリType-erased factories

この最適化により、module.g.cpp に #include の依存関係がなくなり、1 つの実装クラスで変更が発生するたびに再コンパイルをする必要がなくなります。This optimization avoids the #include dependencies in module.g.cpp so that it need not be recompiled every time any single implementation class happens to change. 結果として、ビルドのパフォーマンスが向上します。The result is improved build performance.

複数のライブラリを含む大規模なプロジェクトに対する module.g.cpp のスマートさと効率の向上Smarter and more efficient module.g.cpp for large projects with multiple libs

module.g.cpp ファイルには、winrt_can_unload_now および winrt_get_activation_factory という名前の 2 つの追加構成可能なヘルパーも含まれるようになっています。The module.g.cpp file now also contains two additional composable helpers, named winrt_can_unload_now, and winrt_get_activation_factory. これらは、それぞれに独自のランタイム クラスが含まれる多数のライブラリで DLL が構成される、大規模なプロジェクト向けに設計されています。These have been designed for larger projects where a DLL is composed of a number of libs, each with its own runtime classes. そのような状況では、DLL の DllGetActivationFactoryDllCanUnloadNow を手動でまとめる必要があります。In that situation, you need to manually stitch together the DLL's DllGetActivationFactory and DllCanUnloadNow. これらのヘルパーにより、見かけ上の実行元のエラーが回避されて、それを行うのがはるかに簡単になります。These helpers make it much easier for you to do that, by avoiding spurious origination errors. cppwinrt.exe ツールの -lib フラグを使って個々のライブラリに (winrt_xxx ではなく) 独自のプリアンブルを提供し、各ライブラリの関数に個別の名前を付けて、明確に組み合わせられるようにすることもできます。The cppwinrt.exe tool's -lib flag may also be used to give each individual lib its own preamble (rather than winrt_xxx) so that each lib's functions may be individually named, and thus combined unambiguously.

コルーチンのサポートCoroutine support

コルーチンのサポートは、自動的に組み込まれます。Coroutine support is included automatically. これまでは、サポートは複数の場所に存在しており、制限が厳しすぎると考えられていました。Previously, the support resided in multiple places, which we felt was too limiting. その後、V2.0 では一時的に winrt/coroutine.h ヘッダー ファイルが必要でしたが、それはもう必要なくなっています。And then temporarily for v2.0, a winrt/coroutine.h header file was necessary, but that's no longer needed. Windows ランタイムの非同期インターフェイスは現在では手書きではなく生成されるようになったため、winrt/Windows.Foundation.h に存在しています。Since the Windows Runtime async interfaces are now generated, rather than hand-written, they now reside in winrt/Windows.Foundation.h. 保守性とサポート性の向上とは別に、resume_foreground などのコルーチン ヘルパーを特定の名前空間ヘッダーの末尾に付加する必要がなくなったことを意味します。Apart from being more maintainable and supportable, it means that coroutine helpers such as resume_foreground no longer have to be tacked on to the end of a specific namespace header. 代わりに、もっと自然に依存関係を組み込むことができます。Instead, they can more naturally include their dependencies. これにより、さらに resume_foreground では特定の Windows::UI::Core::CoreDispatcher での再開をサポートできるだけでなく、特定の Windows::System::DispatcherQueue での再開もサポートできるようになります。This further allows resume_foreground to support not only resuming on a given Windows::UI::Core::CoreDispatcher, but it can now also support resuming on a given Windows::System::DispatcherQueue. 以前は、定義は 1 つの名前空間にのみ存在できたため、両方ではなく、1 つのみをサポートできました。Previously, only one could be supported; but not both, since the definition could only reside in one namespace.

DispatcherQueue のサポートの例を次に示します。Here's an example of the DispatcherQueue support.

...
#include <winrt/Windows.System.h>
using namespace Windows::System;
...
fire_and_forget Async(DispatcherQueueController controller)
{
    bool queued = co_await resume_foreground(controller.DispatcherQueue());
    assert(queued);

    // This is just to simulate queue failure...
    co_await controller.ShutdownQueueAsync();

    queued = co_await resume_foreground(controller.DispatcherQueue());
    assert(!queued);
}

コルーチン ヘルパーも [[nodiscard]] で修飾されるようになったため、使いやすさが向上しています。The coroutine helpers are now also decorated with [[nodiscard]], thereby improving their usability. それらが動作するための co_await を忘れた (または、必要であることを知らなかった) 場合、[[nodiscard]] のため、このような誤りではコンパイラの警告が発生します。If you forget to (or don't realize you have to) co_await them for them to work then, due to [[nodiscard]], such mistakes now produce a compiler warning.

スタック割り当ての診断でのヘルプHelp with diagnosing stack allocations

投影されたクラスと実装クラスの名前は (既定では) 同じで、名前空間のみが異なるため、間違えることがあり、ヘルパーの make ファミリではなく、スタック上に実装を誤って作成する可能性があります。Since the projected and implementation class names are (by default) the same, and only differ by namespace, it's possible to mistake the one for the other, and to accidentally create an implementation on the stack, rather than using the make family of helpers. これは、未解決の参照がまだ処理中にオブジェクトが破棄される可能性があるため、場合によっては診断が困難です。This can be hard to diagnose in some cases, because the object may be destroyed while outstanding references are still in flight. デバッグ ビルドでは、アサーションによってこれが選択されるようになりました。An assertion now picks this up, for debug builds. アサーションではコルーチン内のスタック割り当ては検出されませんが、それでもそのような誤りのほとんどを把握するのに役立ちます。While the assertion doesn't detect stack allocation inside a coroutine, it's nevertheless helpful in catching most such mistakes.

強化されたキャプチャ ヘルパーと可変個引数デリゲートImproved capture helpers, and variadic delegates

この更新では、プロジェクションが実行された型もサポートすることによって、キャプチャ ヘルパーに関する制限が修正されています。This update fixes the limitation with the capture helpers by supporting projected types as well. これは、プロジェクションが実行された型を返すときに、Windows ランタイムの相互運用 API で発生することがあります。This comes up now and then with the Windows Runtime interop APIs, when they return a projected type.

また、この更新では、可変個引数 (非 Windows ランタイム) のデリゲートを作成するときの get_strongget_weak のサポートも追加されています。This update also adds support for get_strong and get_weak when creating a variadic (non-Windows Runtime) delegate.

遅延破棄および破棄中の安全な QI のサポートSupport for deferred destruction and safe QI during destruction

ランタイム クラスのオブジェクトのデストラクターでは、参照カウントを一時的に増加させるメソッドが呼び出されることは珍しくありません。It's not uncommon in the destructor of a runtime class object to call a method that temporarily bumps the reference count. 参照カウントが 0 に戻ると、オブジェクトで 2 回目の破棄が行われます。When the reference count returns to zero, the object destructs a second time. XAML アプリケーションでは、階層の上位または下位にあるクリーンアップの実装を呼び出すために、デストラクター内で QueryInterface (QI) を実行することが必要な場合があります。In a XAML application, you might need to perform a QueryInterface (QI) in a destructor, in order to call some cleanup implementation up or down the hierarchy. しかし、オブジェクトの参照カウントは既に 0 になっているので、その QI も参照カウントのバウンスを構成します。But the object's reference count has already reached zero, so that QI constitutes a reference count bounce, too.

この更新には、0 に達した後で再実行されないようにする、参照カウントのデバウンスのサポートが追加されています。それでも、破棄中に必要な一時的な QI は許可されます。This update adds support for debouncing the reference count, ensuring that once it reaches zero it can never be resurrected; while still allowing you to QI for any temporary that you require during destruction. この手順は特定の XAML アプリケーション/コントロールでは避けられず、C++/WinRT はそれに対する回復力を持つようになっています。This procedure is unavoidable in certain XAML applications/controls, and C++/WinRT is now resilient to it.

実装型で静的な final_release 関数を提供することにより、破棄を遅延できます。You can defer destruction by providing a static final_release function on your implementation type. 最後に残ったオブジェクトへのポインターは、std::unique_ptr の形式で、final_release に渡されます。The last remaining pointer to the object, in the form of a std::unique_ptr, is passed to your final_release. その後、そのポインターの所有権を他のコンテキストに移動できます。You can then opt to move ownership of that pointer to some other context. 二重破棄をトリガーすることなくポインターに対して QI を行っても安全です。It's safe for you to QI the pointer without triggering a double-destruction. ただし、オブジェクトを破棄する時点では、参照カウントに対する正味の変更が 0 になっている必要があります。But the net change to the reference count must be zero at the point you destruct the object.

final_release の戻り値は、voidIAsyncAction などの非同期操作オブジェクト、または winrt::fire_and_forget にすることができます。The return value of final_release can be void, an asynchronous operation object such as IAsyncAction, or winrt::fire_and_forget.

struct Sample : implements<Sample, IStringable>
{
    hstring ToString()
    {
        return L"Sample";
    }

    ~Sample()
    {
        // Called when the unique_ptr below is reset.
    }

    static void final_release(std::unique_ptr<Sample> self) noexcept
    {
        // Move 'self' as needed to delay destruction.
    }
};

次の例では、MainPage が解放されると (最終回で)、final_release が呼び出されます。In the example below, once the MainPage is released (for the final time), final_release is called. その関数は (スレッド プールで) 5 秒間待機してから、ページのディスパッチャーを使って再開します (動作するには QI/AddRef/Release が必要です)。That function spends five seconds waiting (on the thread pool), and then it resumes using the page's Dispatcher (which requires QI/AddRef/Release to work). その後、その UI スレッドでリソースをクリーンアップします。It then cleans up a resource on that UI thread. 最後に、unique_ptr がクリアされることで、MainPage のデストラクターが実際に呼び出されます。And finally it clears the unique_ptr, which causes the MainPage destructor to actually get called. そのデストラクター内でも、DataContext が呼び出され、IFrameworkElement に対する QI が必要です。Even in that destructor, DataContext is called, which requires a QI for IFrameworkElement.

コルーチンとしてとして独自の final_release を実装する必要はありません。You don't have to implement your final_release as a coroutine. しかし、それは動作し、非常に簡単に破棄を別のスレッドに移動できます。この例では、それが行われています。But that does work, and it makes it very simple to move destruction to a different thread, which is what's happening in this example.

struct MainPage : PageT<MainPage>
{
    MainPage()
    {
    }

    ~MainPage()
    {
        DataContext(nullptr);
    }

    static IAsyncAction final_release(std::unique_ptr<MainPage> self)
    {
        co_await 5s;

        co_await resume_foreground(self->Dispatcher());
        co_await self->resource.CloseAsync();

        // The object is destructed normally at the end of final_release,
        // when the std::unique_ptr<MyClass> destructs. If you want to destruct
        // the object earlier than that, then you can set *self* to `nullptr`.
        self = nullptr;
    }
};

COM スタイルの単一インターフェイス継承に対するサポートの向上Improved support for COM-style single interface inheritance

Windows ランタイム プログラミングだけでなく、C++/WinRT は COM 専用 API の作成と使用にも使われます。As well as for Windows Runtime programming, C++/WinRT is also used to author and consume COM-only APIs. この更新では、インターフェイス階層が存在する COM サーバーを実装できるようになります。This update makes it possible to implement a COM server where there exists an interface hierarchy. これには Windows ランタイムには必要ありませんが、一部の COM 実装には必要です。This isn't required for the Windows Runtime; but it is required for some COM implementations.

out パラメーターの適切な処理Correct handling of out params

out パラメーターの処理は難しいことがあります。Windows ランタイム配列の場合は特にそうです。It can be tricky to work with out params; particularly Windows Runtime arrays. この更新では、out のパラメーターと配列に関する誤りに対する C++/WinRT の信頼性と回復性がかなり高くなっています。それらのパラメーターが言語プロジェクションからのものか、生の ABI を使用している COM 開発者からのものか、変数の初期化が一貫していない誤りを誰が行ったかには関係ありません。With this update, C++/WinRT is considerably more robust and resilient to mistakes when it comes to out params and arrays; whether those parameters arrive via a language projection, or from a COM developer who's using the raw ABI, and who's making the mistake of not initializing variables consistently. いずれの場合も、C++WinRT では、ABI に対するプロジェクションが実行された型の引き渡し (リソースの解放を記憶することで)、および ABI で到着したパラメーターのゼロ化またはクリアが、適切に処理されます。In either case, C++/WinRT now does the right thing when it comes to handing off projected types to the ABI (by remembering to release any resources), and when it comes to zeroing out or clearing out parameters that arrive across the ABI.

イベントで確実に処理されるようになった無効なトークンEvents now handle invalid tokens reliably

winrt::event の実装では、無効なトークン値 (配列に存在しない値) で remove メソッドが呼び出された場合が正しく処理されるようになります。The winrt::event implementation now gracefully handles the case where its remove method is called with an invalid token value (a value that's not present in the array).

コルーチンが戻る前にコルーチンのローカルが破棄されるCoroutine locals are now destroyed before the coroutine returns

コルーチン型の従来の実装方法では、コルーチン内のローカルを (最後の中断の前ではなく) コルーチンのリターン/完了の "" で破棄することができました。The traditional way of implementing a coroutine type may allow locals within the coroutine to be destroyed after the coroutine returns/completes (rather than prior to final suspension). この問題を回避するためと他のメリットのため、待機処理の再開は最後の中断まで延期されるようになりました。The resumption of any waiter is now deferred until final suspension, in order to avoid this problem and to accrue other benefits.

Windows SDK バージョン 10.0.17763.0 (Windows 10 バージョン 1809) での新機能と変更点News, and changes, in Windows SDK version 10.0.17763.0 (Windows 10, version 1809)

次の表では、Windows SDK バージョン 10.0.17763.0 (Windows 10 バージョン 1809) での C++/WinRT の新機能と変更点を示します。The table below contains news and changes for C++/WinRT in the Windows SDK version 10.0.17763.0 (Windows 10, version 1809).

新機能または変更された機能New or changed feature 詳細情報More info
破壊的変更Breaking change. コンパイルで、C++/WinRT は Windows SDK からのヘッダーに依存しません。For it to compile, C++/WinRT doesn't depend on headers from the Windows SDK. 後の「Windows SDK ヘッダー ファイルからの分離」をご覧ください。See Isolation from Windows SDK header files, below.
Visual Studio プロジェクト システムの形式が変更されました。The Visual Studio project system format has changed. 後の「C++/WinRT プロジェクトのターゲットを Windows SDK の後のバージョンに変更する方法」をご覧ください。See How to retarget your C++/WinRT project to a later version of the Windows SDK, below.
Windows ランタイム関数にコレクション オブジェクトを渡すため、または独自のコレクション プロパティとコレクション型を実装するための、新しい関数と基底クラスがあります。There are new functions and base classes to help you pass a collection object to a Windows Runtime function, or to implement your own collection properties and collection types. C++/WinRT でのコレクション」をご覧ください。See Collections with C++/WinRT.
C++/WinRT ランタイム クラスで {binding} マークアップ拡張機能を使用できます。You can use the {Binding} markup extension with your C++/WinRT runtime classes. 詳細とコード例については、「データ バインディングの概要」をご覧ください。For more info, and code examples, see Data binding overview.
コルーチンの取り消しのサポートにより、取り消しコールバックを登録できます。Support for canceling a coroutine allows you to register a cancellation callback. 詳細とコード例については、「非同期操作の取り消しとキャンセル コールバック」をご覧ください。For more info, and code examples, see Canceling an asychronous operation, and cancellation callbacks.
メンバー関数を指し示すデリゲートを作成するとき、ハンドラーを登録する時点で、現在のオブジェクト (生の this ポインターのインスタンス) に対する強い参照または弱い参照を確立できます。When creating a delegate pointing to a member function, you can establish a strong or a weak reference to the current object (instead of a raw this pointer) at the point where the handler is registered. 詳細およびコード例については、「イベント処理デリゲートで this ポインターに安全にアクセスする」セクションの「デリゲートとしてメンバー関数を使用する場合」サブセクションをご覧ください。For more info, and code examples, see the If you use a member function as a delegate sub-section in the section Safely accessing the this pointer with an event-handling delegate.
Visual Studio の C++ 標準への適合性が向上することによって発見されたバグが修正されました。Bugs are fixed that were uncovered by Visual Studio's improved conformance to the C++ standard. C++/WinRT の標準準拠の検証に対する LLVM および Clang ツールチェーンの利用も向上しています。The LLVM and Clang toolchain is also better leveraged to validate C++/WinRT's standards conformance. 次の記事で説明されいている問題が発生しなくなります。Why won't my new project compile?I'm using Visual Studio 2017 (version 15.8.0 or higher), and SDK version 17134 (新しいプロジェクトがコンパイルされない理由: Visual Studio 2017 (バージョン 15.8.0 以降) と SDK バージョン 17134 を使用している場合)You'll no longer encounter the issue described in Why won't my new project compile? I'm using Visual Studio 2017 (version 15.8.0 or higher), and SDK version 17134

その他の変更点。Other changes.

  • 破壊的変更Breaking change. winrt::get_abi(winrt::hstring const&) で、HSTRING ではなく void* が返されるようになります。winrt::get_abi(winrt::hstring const&) now returns void* instead of HSTRING. static_cast<HSTRING>(get_abi(my_hstring)); を使って HSTRING を取得できます。You can use static_cast<HSTRING>(get_abi(my_hstring)); to get an HSTRING. ABI の HSTRING との相互運用」をご覧ください。See Interoperating with the ABI's HSTRING.
  • 破壊的変更Breaking change. winrt::put_abi(winrt::hstring&) で、HSTRING* ではなく void** が返されるようになります。winrt::put_abi(winrt::hstring&) now returns void** instead of HSTRING*. reinterpret_cast<HSTRING*>(put_abi(my_hstring)); を使って HSTRING* を取得できます。You can use reinterpret_cast<HSTRING*>(put_abi(my_hstring)); to get an HSTRING*. ABI の HSTRING との相互運用」をご覧ください。See Interoperating with the ABI's HSTRING.
  • 破壊的変更Breaking change. HRESULT が winrt::hresult として投影されるようになります。HRESULT is now projected as winrt::hresult. HRESULT が必要な場合 (型チェックの実行または型の特徴のサポートのため)、winrt::hresultstatic_cast できます。If you need an HRESULT (to do type checking, or to support type traits), then you can static_cast a winrt::hresult. それ以外の場合、C++/WinRT ヘッダーをインクルードする前に unknwn.h がインクルードされていると、winrt::hresult は HRESULT に変換されます。Otherwise, winrt::hresult converts to HRESULT, as long as you include unknwn.h before you include any C++/WinRT headers.
  • 破壊的変更Breaking change. GUID が winrt::guid として投影されるようになります。GUID is now projected as winrt::guid. 実装する API の場合、GUID パラメーターに対して winrt::guid を使用する必要があります。For APIs that you implement, you must use winrt::guid for GUID parameters. それ以外の場合、C++/WinRT ヘッダーをインクルードする前に unknwn.h がインクルードされていると、winrt::guid は GUID に変換されます。Otherwise, winrt::guid converts to GUID, as long as you include unknwn.h before you include any C++/WinRT headers. ABI の GUID 構造体との相互運用」をご覧ください。See Interoperating with the ABI's GUID struct.
  • 破壊的変更Breaking change. winrt::handle_type コンストラクター は、明示的にすることで強化されています (それで不適切なコードを記述することが難しくなっています)。The winrt::handle_type constructor has been hardened by making it explicit (it's now harder to write incorrect code with it). 生のハンドル値を割り当てる必要がある場合は、代わりに handle_type::attach 関数 を呼び出します。If you need to assign a raw handle value, call the handle_type::attach function instead.
  • 破壊的変更Breaking change. WINRT_CanUnloadNowWINRT_GetActivationFactory のシグネチャが変更されています。The signatures of WINRT_CanUnloadNow and WINRT_GetActivationFactory have changed. これらの関数は宣言しないでください。You mustn't declare these functions at all. 代わりに、winrt/base.h をインクルードしてこれらの関数の宣言を含めます (いずれかの C++/WinRT Windows 名前空間ヘッダー ファイルをインクルードすると、自動的にインクルードされます)。Instead, include winrt/base.h (which is automatically included if you include any C++/WinRT Windows namespace header files) to include the declarations of these functions.
  • winrt::clock struct では、from_FILETIME/to_FILETIME は非推奨になり、from_file_time/to_file_time を代わりに使用します。For the winrt::clock struct, from_FILETIME/to_FILETIME are deprecated in favor of from_file_time/to_file_time.
  • IBuffer パラメーターを必要とする API が簡素化されています。APIs that expect IBuffer parameters are simplified. ほとんどの API ではコレクションまたは配列が優先されますが、かなりの API は C++ で簡単に使用するには IBuffer が必要です。Although most APIs prefer collections or arrays, enough APIs rely on IBuffer that it needed to be easier to use such APIs from C++. この更新では、C++ 標準ライブラリ コンテナーによって使用されるのと同じデータ名前付け規則を使用して、IBuffer 実装の背後にあるデータに直接アクセスできます。This update provides direct access to the data behind an IBuffer implementation, using the same data naming convention used by the C++ Standard Library containers. これにより、慣例的に大文字で始まるメタデータの名前との競合も回避されます。This also avoids colliding with metadata names that conventionally begin with an uppercase letter.
  • コード生成の向上: コード サイズの削減、インライン化の向上、ファクトリ キャッシュの最適化に関するさまざまな改善。Improved code generation: various improvements to reduce code size, improve inlining, and optimize factory caching.
  • 不要な再帰を削除しました。Removed unnecessary recursion. コマンド ラインで特定の .winmd ではなくフォルダーを参照するとき、cppwinrt.exe ツールで .winmd ファイルが再帰的に検索されなくなります。When the command-line refers to a folder, rather than to a specific .winmd, the cppwinrt.exe tool no longer searches recursively for .winmd files. cppwinrt.exe ツールでは重複の処理もいっそうインテリジェントになり、ユーザー エラーや不適切な形式の .winmd ファイルに対する回復性が向上しています。The cppwinrt.exe tool also now handles duplicates more intelligently, making it more resilient to user error, and to poorly-formed .winmd files.
  • 強化されたスマート ポインター。Hardened smart pointers. 以前は、新しい値を移動割り当てすると、イベント リボーカーは失効に失敗しました。Formerly, the event revokers failed to revoke when move-assigned a new value. これは、スマート ポインター クラスが自己割り当てを確実に処理しない問題を発見するのに役立ちました。原因は winrt::com_ptr 構造体テンプレートでした。This helped uncover an issue where smart pointer classes weren't reliably handling self-assignment; rooted in the winrt::com_ptr struct template. winrt::com_ptr を修正しました。また、イベント リボーカーが移動セマンティクスを正しく処理するように修正され、割り当て時に失効するようになりました。winrt::com_ptr has been fixed, and the event revokers fixed to handle move semantics correctly so that they revoke upon assignment.

重要

バージョン 1.0.181002.2 とバージョン 1.0.190128.4 の両方で、C++/WinRT Visual Studio Extension (VSIX) に対して重要な変更が行われました。Important changes were made to the C++/WinRT Visual Studio Extension (VSIX), both in version 1.0.181002.2, and then later in version 1.0.190128.4. これらの変更の詳細および既存プロジェクトへの影響については、C++/WinRT の Visual Studio サポートに関するページおよび「VSIX 拡張機能の以前のバージョン」をご覧ください。For details of these changes, and how they affect your existing projects, Visual Studio support for C++/WinRT and Earlier versions of the VSIX extension.

Windows SDK ヘッダー ファイルからの分離Isolation from Windows SDK header files

これは、コードに対する破壊的変更になる可能性があります。This is potentially a breaking change for your code.

C++/WinRT は、コンパイルで Windows SDK からのヘッダー ファイルに依存しなくなります。For it to compile, C++/WinRT no longer depends on header files from the Windows SDK. C ランタイム ライブラリ (CRT) および C++ 標準テンプレート ライブラリ (STL) のヘッダー ファイルでも、Windows SDK ヘッダーがインクルードされなくなります。Header files in the C run-time library (CRT) and the C++ Standard Template Library (STL) also don't include any Windows SDK headers. それにより、標準への準拠が向上し、不注意による依存関係が回避され、防ぐ必要のあるマクロの数が大幅に減ります。And that improves standards compliance, avoids inadvertent dependencies, and greatly reduces the number of macros that you have to guard against.

この独立性は、C++/WinRT の移植性と標準準拠の向上を意味し、クロスコンパイラおよびクロスプラットフォーム ライブラリになる可能性を促進します。This independence means that C++/WinRT is now more portable and standards compliant, and it furthers the possibility of it becoming a cross-compiler and cross-platform library. また、C++/WinRT ヘッダーがマクロに悪影響を及ぼさないことも意味します。It also means that the C++/WinRT headers aren't adversely affected macros.

以前はプロジェクトへの Windows ヘッダーのインクルードを C++/WinRT に任せていた場合、自分でインクルードすることが必要になります。If you previously left it to C++/WinRT to include any Windows headers in your project, then you'll now need to include them yourself. いずれの場合も常に、依存するヘッダーを明示的にインクルードし、別のライブラリによって自動的にインクルードされるままにしないのが、ベスト プラクティスです。It is, in any case, always best practice to explicitly include the headers that you depend on, and not leave it to another library to include them for you.

現時点では、Windows SDK ヘッダー ファイルの分離に対する例外は、組み込み関数と数値だけです。Currently, the only exceptions to Windows SDK header file isolation are for intrinsics, and numerics. これらの最後に残っている依存関係に関する既知の問題はありません。There are no known issues with these last remaining dependencies.

プロジェクトでは、必要に応じて、Windows SDK ヘッダーとの相互運用を再度有効にできます。In your project, you can re-enable interop with the Windows SDK headers if you need to. たとえば、COM インターフェイスを実装することが必要な場合があります、(原因は IUnknown)。You might, for example, want to implement a COM interface (rooted in IUnknown). その例では、すべての C++/WinRT ヘッダーをインクルードする前に、unknwn.h をインクルードします。For that example, include unknwn.h before you include any C++/WinRT headers. そのようにすると、C++/WinRT の基本ライブラリで、クラシック COM インターフェイスをサポートするためのさまざまなフックが有効になります。Doing so causes the C++/WinRT base library to enable various hooks to support classic COM interfaces. コードの例については、「C++/WinRT での COM コンポーネントの作成」をご覧ください。For a code example, see Author COM components with C++/WinRT. 同様に、呼び出そうとする型や関数が宣言されている他の Windows SDK ヘッダーを明示的にインクルードします。Similarly, explicitly include any other Windows SDK headers that declare types and/or functions that you want to call.

C++/WinRT プロジェクトのターゲットを Windows SDK の後のバージョンに変更する方法How to retarget your C++/WinRT project to a later version of the Windows SDK

コンパイラとリンカーの問題が最も少なくなるようにプロジェクトのターゲットを変更する方法は、手間も最もかかります。The method for retargeting your project that's likely to result in the fewest compiler and linker issue is also the most labor-intensive. その方法では、新しいプロジェクトを (選択した Windows SDK のバージョンをターゲットにして) 作成した後、古いプロジェクトから新しいプロジェクトにファイルをコピーします。That method involves creating a new project (targeting the Windows SDK version of your choice), and then copying files over to your new project from your old. 古い .vcxproj および .vcxproj.filters ファイルには、コピーして Visual Studio のファイルに保存して追加するだけでよいセクションがあります。There will be sections of your old .vcxproj and .vcxproj.filters files that you can just copy over to save you adding files in Visual Studio.

ただし、Visual Studio でプロジェクトのターゲットを変更するには、他に 2 つの方法があります。However, there are two other ways to retarget your project in Visual Studio.

  • プロジェクトのプロパティ [全般] > [Windows SDK バージョン] に移動し、 [すべての構成][すべてのプラットフォーム] を選択します。Go to project property General > Windows SDK Version, and select All Configurations and All Platforms. [Windows SDK バージョン] を、ターゲットにするバージョンに設定します。Set Windows SDK Version to the version that you want to target.
  • ソリューション エクスプローラーで、プロジェクト ノードを右クリックし、 [プロジェクトの再ターゲット] をクリックして、ターゲットにするバージョンを選択してから、 [OK] をクリックします。In Solution Explorer, right-click the project node, click Retarget Projects, choose the version(s) you wish to target, and then click OK.

これら 2 つの方法のいずれかを使用した後で、コンパイラ エラーまたはリンカー エラーが発生する場合は、もう一度ビルドを試みる前に、ソリューションをクリーニングしてみることができます ( [ビルド] > [ソリューションのクリーン] を選択するか、すべての一時フォルダーとファイルを手動で削除します)。If you encounter any compiler or linker errors after using either of these two methods, then you can try cleaning the solution (Build > Clean Solution and/or manually delete all temporary folders and files) before trying to build again.

C++ コンパイラで "エラー C2039: 'IUnknown': '`<グローバル名前空間>'' のメンバーではありません" が発生する場合は、#include <unknwn.h>pch.h ファイルの先頭に追加します (すべての C++/WinRT ヘッダーをインクルードする前)。If the C++ compiler produces "error C2039: 'IUnknown': is not a member of '`global namespace''", then add #include <unknwn.h> to the top of your pch.h file (before you include any C++/WinRT headers).

その後で、#include <hstring.h> の追加も必要な場合があります。You may also need to add #include <hstring.h> after that.

C++ リンカーで "エラー LNK2019:関数 _VSDesignerCanUnloadNow@0 で参照されている外部シンボル _WINRT_CanUnloadNow@0 は未解決です" が発生する場合は、#define _VSDESIGNER_DONT_LOAD_AS_DLLpch.h ファイルに追加することで解決できます。If the C++ linker produces "error LNK2019: unresolved external symbol _WINRT_CanUnloadNow@0 referenced in function _VSDesignerCanUnloadNow@0", then you can resolve that by adding #define _VSDESIGNER_DONT_LOAD_AS_DLL to your pch.h file.