Home / プログラミング / C++ / VC++のC++規格対応状況
VC++のC++規格対応状況

Microsoft Visual C++ (以下VC++)のC++規格対応状況についてまとめています。

概要

VC++は、他の主要なC++コンパイラ(gcc、clang)と比べ、C++規格への対応状況が芳しくありません。
とはいえ、IDE自体は使いやすいですし、そもそも仕事等でVC++を使わざるを得ない状況はどうしてもあります。
そういった場合に、今使っているVC++のバージョンでどこまでC++11以降の規格を使ってコードを書けるのか簡単にわかるようにこのページを作成しました。

コンパイラバージョン一覧

略称は後述の規格対応表で用います。

VC++バージョン略称_MSC_VER の値備考
Visual C++ 200820081500
Visual C++ 201020101600
Visual C++ 201220121700
Visual C++ Compiler November 2012 CTP2012 CTP1700コンパイラのみの更新。IntelliSense等は非対応。
Visual C++ 201320131800
Visual C++ Compiler November 2013 CTP2013 CTP1800コンパイラのみの更新。IntelliSense等は非対応。
Visual C++ 201520151900

規格対応表

現在は言語機能についてのみリストアップしています。

C++11

規格対応表説明等
2008201020122012
CTP
20132013
CTP
2015
extern templateextern template class std::vector<MyClass>;
long long int 型long long n = 0LL; unsigned long long u = 1ULL;
連続した右山括弧の解釈テンプレートの右山括弧が連続しても右シフト演算子として解釈しない。
override*1*2メンバ関数オーバライドの明示。
C99対応:可変引数マクロ*3*4*5*6*7*8*9#define DEBUG_PRINTF(f,...) std::printf(f, __VA_ARGS__)
auto型推論: auto itr = vec.begin();
nullptrnullポインタリテラル。 0NULL の代わりに使う。
static_assertコンパイル時アサート。 static_assert(sizeof(int) == 4, "error");
新しい関数宣言構文戻り値の型を後置する。 auto func() -> int;
拡張friend宣言template<typename T> class MyClass { friend T; };
ローカル型、無名型の
テンプレート引数使用
struct { int n; } x; std::vector<decltype(x)> v;
ラムダ式*10関数オブジェクトを返す式。 [](int n){ return n * 2; };
decltype*11*12式や関数の型を返す。 decltype(x + y) n = x + y;
enum class強い型付けを持つ列挙型。 enum class E { A, B }; E e = E::A;
列挙型の基盤型指定enum E : char { E_A, E_B }; のように基盤型を指定できる。
列挙型の前方宣言enum E : int; のように列挙型を前方宣言できる。
範囲for文Range-based for: for (auto n : nums) { func(n); }
finalメンバ関数オーバライドの禁止。
rvalue参照とムーブセマンティクス*13*14*15T&&, std::move, std::forward, etc...
明示的型変換演算子explicit operator T() const;
生文字リテラルR"(") とで括った中に特殊文字や改行等をそのまま書ける。
関数テンプレートの
デフォルトテンプレート引数
template<typename T = int> T func();
委譲コンストラクタコンストラクタの初期化子で同クラスの他のコンストラクタを呼び出せる。
可変引数テンプレートVariadic Templates: template<typename ... Types>
統一的な初期化構文Uniform initialization: int n{ 0 }; std::vector<int> v{ 1, 2 };
初期化子リスト*16*17*18std::initializer_list<T> による初期化子リストの受け取り。
default/delete指定コンストラクタ等の自動生成を明示したり禁止したりできる。
Template aliasestemplate<typename T> using array10<T> = std::array<T, 10>;
メンバ変数の宣言時初期化*19*20struct MyStruct { int n = 3; std::string s = "ABC"; };
alignas変数のアラインメントの指定ができる。
alignof型のアラインメントを取得できる。
noexcept修飾関数の例外送出有無を明示する。 void func() noexcept;
メンバ関数の
lvalue/rvalue参照修飾
メンバ関数を &&& で修飾して呼び出し制御できる。
継承コンストラクタ基本クラスのコンストラクタを継承。 struct U : T { using T::T; };
拡張sizeofインスタンス生成せずメンバ変数に対して sizeof(T::value) と書ける。
C99対応:__func__プリプロセスで関数名に変換されるマクロ。
constexpr*21*22constexpr による関数戻り値の定数化等。
char16_t, char32_tUTF-16、UTF-32文字型。
Unicode文字列リテラルu"UTF-16"; U"UTF-32"; u8"UTF-8";
inline namespace1つ外側の名前空間に透過される名前空間。
noexcept演算子式が例外を投げる可能性があるか否かを返す。
thread_localスレッドローカル記憶域。 thread_local int n = 100;
ユーザ定義リテラルリテラルのサフィックスとその処理を独自に定義できる。
無制限の共用体共用体メンバにクラス型を持てる。
ユニバーサル文字名const char* \u3042 = "\U00000041"; // あ = "A" と同義
属性構文[[attr]] 構文による属性指定。

C++14

規格対応表説明等
2008201020122012
CTP
20132013
CTP
2015
decltype(auto)戻り値等をそのままの型で受け取る。 decltype(auto) r = getRefInt();
通常関数の戻り値型推論関数の戻り値型を推論。 auto func() { return 1; } // 戻り値型は int
ジェネリックラムダ式[](auto x, decltype(x) y){ return x + y; };
汎用ラムダキャプチャ[x = x + 1, &y = y]{ return x + y; };
2進数リテラルint n = 0b11001100;
数値リテラルの桁区切りシングルクォートによる桁区切り。 int n = 1'234'567;
サイズ付きのdelete演算子*23void operator delete(void*, std::size_t) noexcept;
動的配列void func(std::size_t n) { int nums[n]; /* ... */ }
変数テンプレートtemplate<typename T> constexpr T zero = static_cast<T>(0);
メンバ変数の宣言時初期化を
含む型の集成体初期化
struct S { int n = 0; }; S s = { 1 };
constexpr関数の制約緩和constexpr 関数でローカル変数の宣言等々を許可する。
初期化子リストの制約緩和集成体の初期化条件を緩和。
[[deprecated]]属性非推奨機能であることを示す属性指定。

参考サイト

*1 *2  デストラクタには指定できない。
*3 *4 *5 *6 *7 *8 *9 *11 *12  バグが多い模様。
*10  関数ポインタへの暗黙の変換等には非対応。
*13 *14 *15  ムーブコンストラクタとムーブ代入演算子の暗黙の定義には非対応。
*16  標準ライブラリは非対応。
*17 *18 *19 *20  メンバ変数の宣言時初期化に初期化子リストが利用できない。
*21  コンストラクタやメンバ関数の修飾は不可。標準ライブラリは非対応。
*22  関数テンプレートにおけるオプショナルな constexpr 指定に非対応。リテラルクラスは配列リテラル、集成体リテラル、暗黙のデフォルトコンストラクタの constexpr 指定に非対応。標準ライブラリは非対応。
*23  コンパイラのサポートが不十分らしい。