C++言語機能(C++11/14/17/20)の中で、特に使いそうなもの
しばらくぶりに、C++のプログラム開発を本格的に行うことになりそうなため、使いそうな拡張言語機能の確認をしています。
cpprefjp – C++日本語リファレンス
拡張言語機能について、日本語で良くまとめられているサイト。
C++言語仕様のバージョンアップで、何が行われてきたか状況把握できます。
以下は、それぞれのバージョンにおける拡張で、直近使うことになりそうなものを、できるだけ少ない数としてピックアップしています。知らなくても使うことになりそうな拡張は、あえてピックアップしていません。
また、機能の非推奨化と削除については、転載させて頂いています。
C++11
auto | 型推論 |
decltype | 式の型を取得 |
範囲for文 | 配列やコンテナといった範囲を表すオブジェクトを、簡潔に走査する |
初期化子リスト | 波括弧による初期化をユーザー定義する。vector<int> v = {1, 2, 3}; など。 |
一様初期化 | コンストラクタの呼び出しを、波カッコで行う。T x {a, b, c}; |
右辺値参照・ムーブセマンティクス | 右辺値によるオーバーロード、およびそれによるリソースの所有権移動 |
ラムダ式 | 関数オブジェクトをその場に書く |
noexcept | 関数の例外指定、例外を投げる可能性のある式かbool 値を返す演算子 |
constexpr | 定数式 |
nullptr | ヌルポインタを表すポインタリテラル |
インライン名前空間 | ネストした名前空間に、透過的にアクセスする |
ユーザー定義リテラル | リテラルのサフィックスをユーザー定義する |
関数のdefault /delete 宣言 | 自動定義される特殊関数の制御 |
移譲コンストラクタ | コンストラクタから他のコンストラクタに処理を移譲する |
非静的メンバ変数の初期化 | メンバ変数を、宣言と同時に初期値指定する |
継承コンストラクタ | 基底クラスのコンストラクタを継承する |
override とfinal | メンバ関数のオーバーライド指定、および派生クラスでのオーバーライドの禁止を指定する |
スコープを持つ列挙型 | 強い型付けとスコープを持つ列挙型の導入と、それにともなって従来の列挙型を機能拡張 |
共用体の制限解除 | 共用体のメンバ変数として、クラスオブジェクトを持てるようにする |
extern template | テンプレートのインスタンス化を抑止する |
スレッドローカルストレージ | スレッドごとに異なる静的記憶域に保持される変数 |
ブロックスコープを持つstatic 変数初期化のスレッドセーフ化 | 関数ローカルで定義したstatic 変数の初期化を、スレッドセーフにする |
戻り値の型を後置する関数宣言構文 | 戻り値の型を後ろに書けるようにすることで、パラメータオブジェクトを戻り値型の文脈で使用できるようにする |
コンパイル時アサート | コンパイル時に条件式が真であることを表明する |
生文字列リテラル | 文字列リテラルにRプレフィックスを付けることで、エスケープシーケンスを無視する |
UTF-8文字列リテラル | char の文字列をUTF-8エンコーディングするプレフィックス |
属性構文 | [[attr]] 構文による、クラス、関数、変数の属性指定 |
alignas | アライメントを指定する |
入れ子名の指定にグローバルスコープ:: を付加することを許可 | struct ::A {}; のように入れ子名を指定する際にグローバルスコープから指定できるようになった |
宣言時に要素数を指定した配列オブジェクトの、定義時の要素数を規定 | static メンバやextern として宣言した配列を定義した際、宣言時に指定した要素数として定義されることが規定された |
sizeof 演算子にクラスの非静的メンバを、オブジェクトを作らずに指定できるようにする | sizeof(T::data_member) のように指定して非静的メンバのサイズを取得する |
可変引数マクロ | マクロで任意の数の引数を受け取る |
事前定義識別子__func__ | 現在いる関数名が格納されている識別子 |
std::array | 固定長配列クラスstd::array を追加 |
emplace() emplace_back() emplace_front() | 要素追加のためのメンバ関数として、クラステンプレートのパラメータT のコンストラクタ引数を受け取り、一時オブジェクトの生成コストを減らせるものが追加された。これらは、以下のように命名されたメンバ関数である:emplace() 、emplace_back() 、emplace_front() |
初期化子リスト | 初期化子リストでコンテナを初期化できるようになった |
std::next() std::prev() | イテレータを進める関数std::next() 、イテレータを逆に進める関数std::prev() を追加 |
std::move_iterator | 要素をムーブするイテレータとして、std::move_iterator クラスを追加 |
std::begin() std::end() | 先頭イテレータと末尾イテレータを取得する非メンバ関数として、std::begin() とstd::end() を追加 |
std::all_of() std::any_of() std::none_of | 範囲が特定の条件を満たしているか調べる、std::all_of() 、std::any_of() 、std::none_of を追加 |
std::copy_n() | 指定された数の要素をコピーするstd::copy_n() を追加 |
std::copy_if() | 条件を満たす要素のみをコピーするstd::copy_if() を追加 |
std::is_sorted() | 範囲がソート済みか調べるstd::is_sorted() を追加 |
std::min() std::max() | 2つの値の最小値を取得するstd::min() 、最大値を取得するstd::max() に、初期化子リストによる可変引数版を追加 |
std::minmax() std::minmax_element() | 最小値と最大値を同時に取得する関数std::minmax() 、std::minmax_element() を追加 |
std::shared_ptr std::unique_ptr | スマートポインタの実装として、所有権共有方式のstd::shared_ptr クラと所有権専有方式のstd::unique_ptr クラスを追加 |
std::u16string std::u32string | UTF-16の文字列型std::u16string 、UTF-32の文字列型std::u32string を追加 |
std::to_string() std::to_wstring() | 数値から文字列オブジェクトに変換する関数として、std::to_string() とstd::to_wstring() を追加 |
std::stoi() std::stof() | 文字列オブジェクトから数値に変換する、std::stoi() やstd::stof() といった関数を追加 |
std::function | 関数ポインタと関数オブジェクトを統一的に扱えるクラスstd::function を追加 |
std::bind() | 関数の引数を束縛して部分適用する関数std::bind() を追加 |
std::mem_fn() | メンバ関数ポインタを関数オブジェクトにアダプトする関数std::mem_fn() を追加 |
std::hash | ハッシュ表コンテナの追加にともない、オブジェクトのハッシュ値を計算する 関数オブジェクト std::hash クラスを追加 |
std::thread | スレッドを管理するクラスstd::thread を追加 |
std::mutex std::recursive_mutex | スレッド間での排他制御を行うミューテックスの実装であるstd::mutex クラス、std::recursive_mutex クラス等を追加 |
std::lock_guard std::unique_loc | ミューテックスの所有権放棄を自動的に行うためのクラスstd::lock_guard 、std::unique_lock を追加 |
std::call_once() | スレッドセーフに一度だけ処理を呼び出す関数、std::call_once() を追加 |
std::condition_variable std::condition_variable_any | 条件変数の実装であるstd::condition_variable クラス、std::condition_variable_any クラスを追加 |
std::future std::promise | Futureデザインパターンをサポートするstd::future クラス、std::promise クラス、およびその補助機能を追加 |
<atomic> | アトミック操作のライブラリ<atomic> を追加 |
std::move() | ムーブセマンティクスのために、左辺値を右辺値に変換する関数std::move() を追加 |
std::tuple | タプルの実装であるstd::tuple クラスを追加 |
<chrono> | 時間ユーティリティライブラリ<chrono> を追加 |
<type_traits> | 型特性ライブラリ<type_traits> を追加 |
<system_error> | OSのエラー値を扱うライブラリ<system_error> を追加 |
<regex> | 正規表現ライブラリ<regex> を追加 |
<random> | 乱数ライブラリ<random> を追加 |
<cstdint> | ビット幅規定の整数型ライブラリである<cstdint> を追加 |
機能の非推奨化 (C++11)
register
キーワードを非推奨化。コンパイラに使われなくなった最適化用の機能を非推奨化- 従来のスマートポインタ
auto_ptr
クラスを、非推奨とする - 従来の関数オブジェクトアダプタ
std::unary_function
、std::binary_function
、std::mem_fun()
、std::mem_fun_ref()
等を非推奨とする - 従来の関数バインダ
std::bind1st
、std::bind2nd
等を非推奨とする
C++14
[[deprecated]] 属性 | 非推奨の機能であることを示す属性 |
std::make_unique() std::make_unique() | std::unique_ptr を生成するヘルパ関数std::make_unique() を追加 |
std::exchange() | 2つの値を入れ替える関数std::exchange() を追加 |
リテラル演算子s | std::basic_string のリテラル演算子s を追加"hello"s は、文字コード未規定のstd::string オブジェクトを表すリテラルL"hello"s は、文字コード未規定のstd::wstring オブジェクトを表すリテラルu8"hello"s は、UTF-8文字コードのstd::string オブジェクトを表すリテラルu"hello"s は、UTF-16文字コードのstd::u16string オブジェクトを表すリテラルU"hello"s は、UTF-32文字コードのstd::u32string オブジェクトを表すリテラル |
各時間単位を表すリテラル | std::chrono::duration の、各時間単位を表す、以下のリテラルを追加ナノ秒単位を表す ns リテラルマイクロ秒単位を表す us リテラルミリ秒単位を表す ms リテラル秒単位を表す s リテラル分単位を表す min リテラル時単位を表す h リテラル |
<shared_mutex> | Readers-writer lockと呼ばれる、書き込みを行うユーザーが1人、読み込みを行うユーザーが複数いる状況で効率的に振る舞うミューテックスの実装として、<shared_mutex> ヘッダを追加 |
C++17
インライン変数 | inline 指定をすることで翻訳単位を跨いでひとつのオブジェクトになる変数を定義する |
構造化束縛 | 組・タプル・配列を展開して変数定義する |
[[nodiscard]] 属性 | 戻り値を捨ててはならないことを指定する |
if 文とswitch 文の条件式と初期化を分離 | if (init; condition) のように初期化と条件式を分けて記述できるようにする |
if constexpr 文 | if constexpr(cond) とすることで、そのif 文はコンパイル時に処理される |
入れ子名前空間の定義 | namespace A::B {} のように、入れ子の名前空間を簡単に定義できるようにする |
例外仕様を型システムの一部にする | 関数の型に例外仕様が含まれるようにする |
非推奨だった古い例外仕様を削除 | throw キーワードによる例外仕様を削除。throw() は残る |
__has_include | インクルードするファイルが存在するかを確認する |
非推奨だったregister キーワードを削除 | コンパイラから単に無視されていたregister キーワードを削除。予約語は残 |
<filesystem> | <filesystem> ヘッダを新設し、ファイルシステムライブラリを追加。ファイル、ディレクトリなどを扱う |
並列実行のオプションを追加 | <algorithm> や<numeric> のアルゴリズムに、並列実行のオプションを追加 |
<any> | <any> ヘッダを新設し、なんでも代入できるany クラスを追加 |
<memory_resource> | 多相アロケータとメモリプール。<memory_resource> が新設され、アロケートする型を規定しないアロケータと、それを利用したメモリプールの仕組みが導入される |
機能の削除 (C++17)
- C++11から非推奨だった古いスマートポインタである
auto_ptr
を削除。代わりにshared_ptr
かunique_ptr
を使用すること - C++14から非推奨だった配列をランダムに入れ替える
random_shuffle()
関数を削除。代わりにshuffle()
を使用すること - C++11から非推奨だった
throw
キーワードによる古い例外仕様に関連する、以下のライブラリ機能を削除するunexpected()
set_unexpected()
get_unexpected()
unexpected_handler
noexcept
による例外仕様では、例外を送出しないはずの関数から例外が送出された場合、terminate()
関数によって即座にプログラムが異常終了するため、想定されていない例外が送出された場合のハンドリングは機能しない
- C++11から非推奨だった古い
<functional>
の機能を削除- 引数を束縛する
bind1st()
関数、bind2nd()
関数、binder1st
クラス、binder2nd
クラスを削除。代わりにbind()
関数やラムダ式を使用すること - 関数ポインタから関数オブジェクトに変換するための
ptr_fun()
関数、pointer_to_unary_function
クラス、pointer_to_binary_function
クラスを削除。first_argument_type
やsecond_argument_type
といった型が必要なくなったため、これらの機能は必要なくなった - メンバ関数から関数オブジェクトへの変換をするための
mem_fun()
関数、mem_fun_ref()
関数、mem_fun_t
クラス、mem_fun1_t
クラス、mem_fun_ref_t
クラス、mem_fun1_ref_t
クラス、const_mem_fun_t
クラス、const_mem_fun1_t
クラス、const_mem_fun_ref_t
クラス、const_mem_fun1_ref_t
クラスを削除。代わりにmem_fn()
、bind()
関数やラムダ式を使用すること
- 引数を束縛する
function
クラスのアロケータサポートを削除。コンパイラが実装していなかったり、不完全な実装だったりしていた- C++98から非推奨だったiostreamのエイリアスを削除
ios_base::io_state
の代わりにios_base::iostate
を使用することios_base::open_mode
の代わりにios_base::openmode
を使用することios_base::seek_dir
の代わりにios_base::seekdir
を使用することios_base::streamoff
の代わりに、char_traits<CharT>::off_type
もしくはbasic_ios<CharT>::off_type
を使用すること (<iosfwd>
で定義されているstd::streamoff
は残る)ios_base::streampos
の代わりに、char_traits<CharT>::pos_type
もしくはbasic_ios<CharT>::pos_type
を使用すること (<iosfwd>
で定義されているstd::streampos
は残る)basic_streambuf::stossc()
メンバ関数を削除。sbumpc()
の単なる別名ios_base
クラスの別名型が削除されることにともない、それらの型をパラメータにとるオーバーロードを削除ios_base
クラスの別名型が削除されることにともない、それらの型をパラメータにとる関数が削除
機能の非推奨化 (C++17)
std::iterator
クラスを非推奨化。このクラスを使用しても、イテレータ定義は簡単にならなかった- C++11で
allocator_traits
クラスが導入されたことで不要になった、allocator
の以下のメンバを非推奨化:size_type
型difference_type
型pointer
型const_pointer
型reference
型const_reference
型rebind
型address()
メンバ関数allocate()
メンバ関数のhint
パラメータmax_size()
メンバ関数construct()
メンバ関数destroy()
メンバ関数
- C++11で
allocator_traits
クラスが導入されたことで不要になった、要素型を再束縛するためのallocator<void>
特殊化を非推奨化 constexpr
の機能拡張によって扱える型が増えている。将来的にほとんどの型がconstexpr
で扱えるようになるため、constexpr
で扱える型の分類であるis_literal_type
型特性を非推奨化- 一時的なメモリ確保のための
std::get_temporary_buffer()
関数とstd::return_temporary_buffer()
関数を非推奨化。これらは関数内での一時的なメモリ確保のために、最適化されたメモリ確保の仕組みを提供することを期待して定義されたが、実際にはどの実装も特別視せず、それゆえに便利に使われてはこなかった。将来的にスタックからのメモリ確保をする機能を作る予定だが、これらの関数は例外安全性やRAIIが考慮されていないため、これらの関数の実装・仕様のみを入れ替えるような改訂はできない raw_storage_iterator
クラスを非推奨化。アロケータとの連携ができず、限られた用途にしか使用できなかったnot_fn()
の追加にともない、古くなった以下の機能を非推奨化:not1()
関数not2()
関数unary_negate
クラスbinary_nagate
クラス- 標準関数オブジェクトの
result_type
、argument_type
、first_argument_type
、second_argument_type
型
- デバッグ用途にしか使用しない、
shared_ptr::unique()
を非推奨化 result_of
を非推奨化。代わりにinvoke_result
を使用すること<codecvt>
と関連する機能を非推奨化。適切なエラーハンドリングの方法がなかったため、セキュリティ上攻撃の可能性があったmemory_order_consume
を一時的に非推奨化。「その定義が現実に即していない」「acquire/releaseより弱いから使いにくい」といった理由から、より良い定義に変更するまでの間、非推奨とするuncaught_exceptions()
の追加にともない、古くなったuncaught_exception()
を非推奨化
C++20
初期化式をともなう範囲for文 | 範囲for文スコープで使用する変数の初期化のための構文を追加 |
確率が高い分岐と低い分岐を伝える属性 [[likely]] , [[unlikely]] | 条件分岐の最適化ヒントを与える属性 |
入れ子名前空間定義でのインライン名前空間 | namespace ns1::inline ns2::ns3 {} のように、入れ子名前空間を定義する式にインライン名前空間の指定を含められるようにする |
モジュール | ヘッダファイル・ソースファイル、インクルードに変わる仕組みとしてモジュールを導入する |
コルーチン | 関数実行を中断・再開する仕組みとしてコルーチンを導入する |
<source_location> | ソースコードの位置を取得するライブラリとして<source_location> を追加 |
std::make_unique_for_overwrite() std::make_shared_for_overwrite() std::allocate_shared_for_overwrite() | スマートポインタをデフォルト初期化で構築するヘルパ関数として、std::make_unique_for_overwrite() 、std::make_shared_for_overwrite() 、std::allocate_shared_for_overwrite() を追加 |
std::to_address() | ポインタを生ポインタに変換するstd::to_address() を追加 |
機能の削除 (C++20)
throw() による例外送出しない指定を削除 | 代わりにnoexcept を使用すること |
ユーザー宣言したコンストラクタを持つクラスの集成体初期化を禁止 | コンストラクタがdelete 宣言されているクラスを、集成体初期化によってコンストラクタ呼び出しを回避して構築できてしまっていた技法を禁止 |
- C++11で
allocator_traits
クラスが導入されたことでC++17から非推奨化されていた、allocator
の以下のメンバを削除:size_type
型difference_type
型pointer
型const_pointer
型reference
型const_reference
型rebind
型address()
メンバ関数allocate()
メンバ関数のhint
パラメータmax_size()
メンバ関数construct()
メンバ関数destroy()
メンバ関数
- C++11で
allocator_traits
クラスが導入されたことでC++17から非推奨化されていた、要素型を再束縛するためのallocator<void>
特殊化を非推奨化 - C++17で非推奨化されていた、
constexpr
で扱える型の分類であるis_literal_type
型特性を削除 - C++17で非推奨化されていた、一時的なメモリ確保のための
std::get_temporary_buffer()
関数とstd::return_temporary_buffer()
関数を削除 - C++17で非推奨化されていた
raw_storage_iterator
クラスを削除 not_fn()
の追加にともない、C++17から非推奨化されていた以下の機能を削除:not1()
関数not2()
関数unary_negate
クラスbinary_nagate
クラス- 標準関数オブジェクトの
result_type
、argument_type
、first_argument_type
、second_argument_type
型
- C++17から非推奨化されていた
shared_ptr::unique()
を削除 invoke_result
の追加にともない、C++17から非推奨化されていたresult_of
を削除- C++17での
uncaught_exceptions()
の追加にともない、非推奨化していたuncaught_exception()
を削除 - C++17で非推奨化されていたC互換ライブラリ
<ccomplex>
,<cstdalign>
,<cstdbool>
,<ctgmath>
を削除。また、C++ではなにも定義されないC互換ライブラリ<ciso646>
を削除
機能の非推奨化 (C++20)
PODを非推奨化 | |
[=] によるthis の暗黙のキャプチャを非推奨化 | コピーのデフォルトキャプチャでは、this ポインタをキャプチャされなくする |
添字演算子内でのカンマ演算子の使用を非推奨化 | ar[i, j] を非推奨化。ar[(i, j)] はOK |
- 一貫比較非機能によって比較演算子の定義が容易になったため、不要になった演算子の簡潔定義機能である
std::rel_ops
を非推奨化 std::basic_string::reserve()
メンバ関数が、メモリの縮小をしなくなったため、デフォルト引数0
を非推奨可std::atomic
クラスとstd::atomic_flag
クラスのデフォルトコンストラクタが値初期化するようになったため、不要になった以下のアトミックオブジェクトの初期化機能を非推奨化:
C++23
当面先の話
機能の非推奨化 (C++23)
std::algined_storage
とstd::aligned_union
を非推奨化。これらの機能は未定義動作を引き起こし、間違った保証が行われ、よくないAPI設計が行われていたため、非推奨となる。
std::algined_storage
の代わりにalignas(T) std::byte[sizeof(T)];
を使用することを推奨するstd::aligned_union
の代わりにalignas(Ts...) std::byte[std::max({sizeof(Ts)...})];
を使用することを推奨する