C++11 の機能 (Modern C++) のサポート

ここでは、Visual C++ の C++11 機能について説明します。

この記事の内容

  • C++11 Feature List

    • Core Language Feature Table

    • Core Language Feature Table: Concurrency

    • Core Language Feature Table: C99

  • Guide To Feature Tables

    • Rvalue References

    • Lambdas

    • decltype

    • Strongly Typed/Forward Declared enums

    • Alignment

    • Standard-Layout and Trivial Types

    • Defaulted and deleted functions

    • override and final

    • Atomics, and more

    • C99 __func__ and preprocessor rules

  • Standard Library features

C++11 機能の一覧

Visual Studio 2010 の Visual C++ では、C++11 コア言語仕様の数多くの機能が実装されましたが、Visual Studio 2012 の Visual C++ ではさらに機能が追加されました。 Visual Studio 2013 の Visual C++ でも C++11 機能が追加され、C++14 ライブラリ機能の一部もサポートされています。 次の表に、Visual Studio 2010 の Visual C++、Visual Studio 2012 の Visual C++、および Visual Studio 2013 の Visual C++ での C++11 コア言語機能と実装の状態を示します。

C++11 コア言語機能の表

C++11 コア言語機能

Visual Studio 2010

Visual Studio 2012

Visual Studio 2013

右辺値参照 v0.1v1.0v2.0v2.1v3.0

v2.0

v2.1*

v2.1*

ref 修飾子

非静的データ メンバーの初期化子

可変値引数テンプレート v0.9v1.0

初期化子リスト

static_assert

auto v0.9v1.0

v1.0

v1.0

v1.0

後続の戻り値の型

ラムダ v0.9v1.0v1.1

v1.0

v1.1

v1.1

decltype v1.0v1.1

v1.0

v1.1**

v1.1

右山かっこ

関数テンプレートに関する既定のテンプレート引数

SFINAE 式

エイリアスのテンプレート

extern テンプレート

nullptr

厳密に型指定された列挙型

Partial

事前宣言列挙型

属性

constexpr

アラインメント

TR1

Partial

Partial

コンストラクターのデリゲート

コンストラクターの継承

明示的な変換演算子

char16_t/char32_t

Unicode 文字列リテラル

未加工の文字列リテラル

リテラルのユニバーサル文字名

ユーザー定義リテラル

標準レイアウトと単純型

既定化および削除指定関数

○*

拡張されたフレンド宣言

拡張 sizeof

インライン名前空間

無制限の共用体

テンプレート引数としてのローカル型および名前のない型

範囲ベースの for-loop

override および final v0.8v0.9v1.0

Partial

最小限の GC サポート

noexcept

[go to top]

C++11 コア言語機能の表: 同時実行

C++11 コア言語機能: 同時実行

Visual Studio 2010

Visual Studio 2012

Visual Studio 2013

繰り返しシーケンス ポイント

N/A

N/A

N/A

アトミック

厳密な比較および交換

双方向フェンス

メモリ モデル

N/A

N/A

N/A

データ依存関係の順序付け

データ依存関係の順序付け: 関数の注釈

exception_ptr

quick_exit

通知ハンドラー内のアトミック

スレッド ローカル ストレージ

Partial

Partial

Partial

静的マジック

[go to top]

C++11 コア言語機能: C99

C++11 コア言語機能: C99

Visual Studio 2010

Visual Studio 2012

Visual Studio 2013

__func__

Partial

Partial

Partial

C99 プリプロセッサ

Partial

Partial

Partial

long long

長整数型

N/A

N/A

N/A

[go to top]

機能一覧表の手引き

右辺値参照

注意

以下の説明にあるバージョン番号 (v0.1、v1.0、v2.0、v2.1、v3.0) は、C++11 の進化を示す目的で付けたものです。標準自体では、これらのバージョン番号は使用されていません。

N1610「右辺値によるクラス オブジェクトの初期化の明確化」は、右辺値参照なしでセマンティクスを移動する初期の試みでした。 ここでは、これを "右辺値参照 v0.1" と呼びます。 これは、"右辺値参照 v1.0" に置き換えられました。Visual Studio 2010 の Visual C++ の動作のベースとなっていた "右辺値参照 v2.0" は、右辺値参照が左辺値にバインディングされるのを防ぐため、安全上の大きな問題が解決されます。" 右辺値参照 v2.1" では、この規則が改良されています。 オーバーロード push_back(const string&) および push_back(string&&) と、呼び出し v.push_back("strval") を持つ vector<string>::push_back() を検討してください。 "strval" 式は文字列リテラルであり、lvalue です。 (整数 1729 など、他のリテラル右辺値ですが、配列であるためリテラル文字列は特殊です)。"右辺値参照 v2.0" の規則は、"strval" は左辺値であるため string&& を "strval" にバインディングすることはできず、その結果 push_back(const string&) が使用できる唯一のオーバーロードになると述べています。 これにより、一時的な std::string が作成されてベクターにコピーされ、一時的な std::string が破棄されます。このことはあまり効率的ではありません。 "右辺値参照 v2.1" の規則は、string&& を "strval" にバインディングすると一時的な std::string が作成され、一時的に右辺値になることを認めています。 したがって、push_back(const string&) と push_back(string&&) の両方とも使用できますが、push_back(string&&) が推奨されます。 一時的な std::string は構築された後、ベクターに移動されます。 この方が効率的です。

"右辺値参照 v3.0" は、一定の条件下で移動コンストラクターと移動代入演算子を自動的に生成する新しい規則を追加します。 ただし、これは時間とリソースの制約により Visual Studio 2013 の Visual C++ には実装されていません。

[go to top]

ラムダ

ラムダ関数が投票で報告書に追加され (バージョン "0.9")、変更可能なラムダが追加された (バージョン "1.0") 後、標準化委員会が表現を徹底的に見直しました。 これにより、ラムダ バージョン "1.1" が生成され、現在、完全にサポートされています。 ラムダ v1.1 の表現では、静的メンバーまたは入れ子になったラムダを参照するなどのコーナー ケースで何が起きるかが明確になっています。 これにより、複雑なラムダによって生じる問題が修正されます。 また、ステートレス ラムダ関数を関数ポインターに変換できるようになりました。 これは、N2927 の表現にはありませんが、ラムダ v1.1 の一部としてはカウントされます。 C++11 5.1.2 [expr.prim.lambda]/6 では、lambda-capture のない lambda-expression のクロージャ型には、クロージャ型の関数呼び出し演算子と同じパラメーターおよび戻り値の型を持つ関数へのポインターに変換する、仮想および明示的でないパブリック const 変換関数があります。 この変換関数によって返される値は、呼び出されたときに、クロージャ型の関数呼び出し演算子と同じ効果を持つ関数のアドレスになります」という説明があります (Visual Studio 2012 の Visual C++ の実装では、任意の呼び出し規約を持つ関数ポインターにステートレス ラムダを変換可能になったため、かなり改善されました。 これは、__stdcall 関数ポインターなどを必要とする API を使用している場合は重要です)。

[go to top]

decltype

decltype が投票で報告書に追加された後 (バージョン 1.0)、直前になって小さいけれども重要な修正が加えられました (バージョン 1.1)。 これは、STL と Boost を使用するプログラマにとっては大きな関心事です。

[go to top]

厳密に型指定された列挙型/事前宣言列挙型

厳密に型指定された列挙型は、Visual Studio 2010 の Visual C++ では部分的にサポートされていました (具体的には、明示的に指定された基になる型に関するパート)。 これらは現在、Visual Studio に完全に実装され、事前宣言列挙型の C++11 セマンティクスも完全に実装されています。

[go to top]

アラインメント

投票によって報告書に追加されたアラインメントに関する提案のコア言語キーワード alignas/alignof は実装されていません。 Visual Studio 2010 の Visual C++ には、TR1 の aligned_storage がありました。 Visual Studio 2012 の Visual C++ では、標準ライブラリに aligned_union と std::align() が追加され、Visual Studio 2013 の Visual C++ では主要な問題が修正されました。

[go to top]

標準レイアウトと単純型

N2342「POD の再考: 核となる問題 568 (リビジョン 5)」の公開された変更は、標準テンプレート ライブラリの <type_traits> への is_trivial と is_standard_layout の追加でした (N2342 では、コア言語に関する多くの表現が改められましたが、コンパイラの変更は必要ありません)。これらの型の特徴は Visual Studio 2010 の Visual C++ で使用可能でしたが、is_pod を複製しただけでした。 したがって、このドキュメントにある上の表ではサポートが "いいえ" となっています。 現在では、正確な応答を提供するコンパイラ フックにより強化されています。

Visual Studio 2013 の Visual C++ では、強く求められていた STL の common_type<> の修正が行われました。 C++11 仕様の common_type<> では、予期しない結果が生じることがありました。特に、common_type<int, int>::type が int&& を返すことは問題でした。 そこで、Visual Studio 2013 の Visual C++ ではライブラリ ワークグループの懸案事項 2141 に対して推奨される解決が実装され、common_type<int, int>::type が int を返すようになりました。

この変更の副作用として、ID の場合に機能しなくなりました。common_type<T> が常に型 T になるとは限らないからです。 これは、上記の「推奨される解決」に準拠していますが、コードの互換性に影響があります。

ID 型の特徴が必要な場合、<type_traits> で定義された非標準の std::identity は <void> で機能しないので使用しないでください。 代わりに、要件に応じた独自の ID 対応の動作を実装します。 次に例を示します。

template <typename T> struct Identity {
    typedef T type;
};

注意

互換性に影響する他の変更については、「Visual C++ での互換性に影響する変更点」を参照してください。

[go to top]

既定化および削除指定関数

これらの機能は現在サポートされていますが、例外として、既定化関数では、 =default を使用したメンバー関数の移動コンストラクターと移動代入演算子の要求はサポートされていません。 移動とコピーは、正確に標準どおりには動作していません。たとえば、標準では移動を削除した場合はコピーも抑制されることになっていますが、Visual Studio 2013 の Visual C++ ではそうではありません。

既定化および削除指定関数の詳細については、「C++ 関数定義」を参照してください。

[go to top]

オーバーライドと最終

これは、短くて複雑な進化を経てきました。 もともと、バージョン 0.8 には [[override]]、[[hiding]]、[[base_check]] の各属性がありました。 その後、バージョン 0.9 では、これらの属性が削除され、コンテキスト キーワードに置き換えられました。 最後に、バージョン 1.0 で、クラスの "final" と、関数の "override" および "final" に減りました。 したがって、これは上昇拡張になります。Visual Studio 2010 の Visual C++ では既にこの "override" 構文が関数でサポートされており、C++11 のセマンティクスとある程度近いセマンティクスを持っていたためです。" final" もサポートされていましたが、スペルが異なっていて、"sealed" というものでした。 "override" と "final" の標準スペルとセマンティクスが完全にサポートされるようになりました。 詳細については、「override 指定子」および「final 指定子」を参照してください。

[go to top]

アトミックおよびその他

アトミック厳密な比較および交換双方向フェンス、およびデータ依存関係の順序付けは、現在実装されている標準ライブラリ メカニズムを指定します。

関連する STL ヘッダー: <atomic><chrono><condition_variable><future><mutex><ratio><scoped_allocator>、および <thread>

[go to top]

C99 の __func__ およびプリプロセッサ規則

Core Language Feature Table: C99 の表には、2 つの項目に対して "Partial" の実装が示されています。 定義済みの識別子 __func__ の場合は、非標準の拡張機能 __FUNCDNAME__、__FUNCSIG__、および __FUNCTION__ がサポートされているため、"Partial" が示されています。 詳細については、「定義済みマクロ」を参照してください。 C99 プリプロセッサ規則の場合、可変個引数マクロがサポートされているため、"Partial" が示されています。 詳細については、「Variadic マクロ」を参照してください。

[go to top]

標準ライブラリの機能

これは、コア言語をカバーします。 C++11 の標準ライブラリに関する機能の詳しい比較表はありませんが、Visual Studio 2012 の Visual C++ にも実装されています。ただし、2 つの例外があります。 1 つ目の点として、ライブラリの機能がコンパイラにない機能に依存していた場合は、必要な機能をシミュレートするか (たとえば、make_shared<T>() の可変個引数テンプレートをシミュレートしました)、実装しませんでした (このようなケースはほとんどなく、目立った例としては <initializer_list> がありましたが、これも Visual Studio 2013 の Visual C++ では完全に実装されています)。C99 はごくわずかな例外を除いて Visual Studio 2013 の Visual C++ で実装されており、C++ のラッパー ヘッダーが提供されています。 詳細については、「Visual Studio 2013 での C99 ライブラリのサポート」を参照してください。

Visual Studio 2012 の Visual C++ と Visual Studio 2013 の Visual C++ での変更の一部を次に示します。

配置: C++11 により要求されているように、emplace()/emplace_front()/emplace_back()/emplace_hint()/emplace_after() は "任意の" 数の引数のすべてのコンテナーに実装されています (「シミュレートされた可変個引数」を参照)。 たとえば、vector<T> には、完全に転送される任意の数の任意の引数からベクターの背後で型 T の要素を直接構築する "template <typename... Args> void emplace_back(Args&&... args)" があります。 これは、余分な移動の構築と破棄が必要な push_back(T&&) よりも効率的な場合があります。

可変個引数: Visual Studio 2012 の Visual C++ には、可変個引数テンプレートをシミュレートするためのスキームがありました。 Visual Studio 2013 の Visual C++ では、シミュレーションがなくなり、可変個引数が完全に実装されています。 コードが従来のシミュレートされた可変個引数の動作に依存している場合は、修正する必要があります。 ただし、実際の可変個引数テンプレートに切り替えることにより、コンパイル時間の改善コンパイラのメモリ使用量の削減が実現します。

明示的な変換演算子: コア言語において、明示的な変換演算子は一般的な機能です。たとえば、explicit operator MyClass()" を持つことができます。 ただし、現在、標準ライブラリで使用されているのは、クラスの安全なブール値検証を実現する explicit operator bool() という 1 つの形式のみです (単純な "operator bool()" は危険なことでよく知られています)。以前、Visual C++ によってシミュレートされた operator pointer-to-member() と explicit operator bool() の組み合わせによって各種の問題が発生し、効率の大きな妨げとなっていました。 現在、この擬似「ブール」の回避策は完全に削除されています。

ランダム性: uniform_int_distribution への先入観が完全になくなり、mersenne_twister などの Uniform Random Number Generator を直接受け入れる shuffle() が <algorithm> に実装されています。

オーバーロードされた address-of 演算子の禁止: C++98/03 では、STL コンテナーの要素により、address-of 演算子のオーバーロードを禁止しています。 これは、CAdapt などのヘルパー クラスにそのようなオーバーロードから STL を保護することを要求するため、CComPtr などのクラスがこ行います。 Visual Studio 2010 の Visual C++ の開発時、STL の変更により、さらに多くの状況でオーバーロードされた address-of 演算子が禁止されるようになりました。 C++11 では、オーバーロードされた address-of 演算子を許容可能にするため、要件が変更されました。 C++11 および Visual Studio 2010 の Visual C++ には、演算子のオーバーロードに関係なくオブジェクトの実際のアドレスを取得できるヘルパー関数 std::addressof() が用意されています。 Visual Studio 2010 の Visual C++ がリリースされる前は、"&elem" のオカレンスを禁止度合が妥当な "std::addressof(elem)" に置き換えるよう試みていました。 Visual Studio 2012 の Visual C++ ではさらに進んで、address-of 演算子をオーバーロードするクラスが STL 全体で使用できるようになりました。

Visual Studio 2012 の Visual C++ が C++11 より優れていた点:

SCARY 反復子: C++11 標準により要求されていませんが許可されているとおり、SCARY 反復子が実装されました。この点については、N2911「高速で小さいプログラム向けに汎用クラス内で意依存関係を最小限に抑える」N2980「SCARY 反復子の割り当てと初期化、リビジョン 1」で説明されています。

ファイルシステム: 提案 TR2 による <filesystem> ヘッダーが追加されました。 これにより、recursive_directory_iterator と他の興味深い機能が提供されます。 C++0x の実行がきわめて低速で C++11 に変更されたために TR2 での作業が凍結される前、提案 2006 が Boost.Filesystem V2 から派生しました。 後に Boost.Filesystem V3 に進化しましたが、Visual Studio 2012 の Visual C++ には実装されていません。

さらに、重要な最適化も行われました。 すべてのコンテナーは、現在の表現を考慮して最適な小ささになりました。 これは、ポイントされたコンテンツではなく、コンテナー オブジェクト自体を参照します。 たとえば、std::vector には、3 つの生のポインターが格納されます。 Visual Studio 2010 の Visual C++ では、x86 のリリース モード、std::vector は 16 バイトです。 Visual Studio 2012 の Visual C++ では、12 バイトであり、これは最適な小ささです。 これには大きな効果があります。プログラムに 100,000 のベクターがある場合、Visual Studio 2012 の Visual C++ では 400,000 バイト節約されます。 メモリの使用量が減ると、領域と時間の両方を節約できます。

std::allocator と std::less がステートレスであるため、これは空のアロケーターと比較子の格納を避けることによって実現されました (これらの最適化は、ステートレスである限りカスタム アロケーター/比較子でも有効です。 当然ながら、ステートフル アロケーター/比較子の格納は回避できませんが、きわめてまれです)。

Visual Studio 2013 の Visual C++ は C++11 だけでなく、主要な C++14 ライブラリの機能も実装しています。

  • "透過的な演算子のファンクター" less<>greater<>plus<>multiplies<> など。

  • make_unique<T>(args...) およびmake_unique<T[]>(n)

  • cbegin()/cend()rbegin()/rend()、および crbegin()/crend() の非メンバー関数。

[go to top]

参照

関連項目

C++ でのラムダ式

範囲ベースの for ステートメント (C++)

概念

Visual Studio 2013 における Visual C++ の新機能

Visual C++ での互換性に影響する変更点

その他の技術情報

C++ へようこそ (Modern C++)

C++ 言語リファレンス

C++ 標準ライブラリ リファレンス

Visual C++ チーム ブログ