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_guardstd::unique_loc | ミューテックスの所有権放棄を自動的に行うためのクラスstd::lock_guard、std::unique_lockを追加 |
| std::call_once() | スレッドセーフに一度だけ処理を呼び出す関数、std::call_once()を追加 |
std::condition_variablestd::condition_variable_any | 条件変数の実装であるstd::condition_variableクラス、std::condition_variable_anyクラスを追加 |
std::futurestd::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_handlernoexceptによる例外仕様では、例外を送出しないはずの関数から例外が送出された場合、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)...})];を使用することを推奨する