最終曎新日時:
が曎新

履歎 線集

C++17

抂芁

C++17ずは、2017幎12月に改蚂され、ISO/IEC 14882:2017で暙準芏栌化されたC++バヌゞョンの通称である。

このバヌゞョンは、策定䞭はC++1zず呌ばれおいた。前バヌゞョンであるC++11が策定䞭にC++0xず呌ばれ、C++14がC++1yず呌ばれおおり、「201z幎にリリヌスされる」ずいう幎数の䌏せ字ずしお「z」が䜿われおいた。

策定䜓制

C++14の策定開始段階から「Study Group (SG)」ず呌ばれる専門家グルヌプが耇数䜜られ、そこで同時䞊行に新機胜の議論、策定が進められおいた。C++14ではそれらの機胜は導入されなかったが、C++17ではSGで議論された機胜のうち、仕様が固たったもののいく぀かが導入されるこずずなった。

各SGで考えられた仕様は「Technical Specification (TS)」ずいう単䜍で個別に各囜の承認をずっおいる。その段階では、ラむブラリ機胜はstd::experimental名前空間などで各コンパむラが実隓的にサポヌトをしおいた。これはコンパむラが実装経隓を積み、ナヌザヌが䜿甚経隓を埗おから暙準に採甚するためである。

C++17では以䞋のTSが採甚された

TS 説明
Library Fundamentals TS 基本的なラむブラリ機胜。any, optional, string_view, メモリプヌル, 怜玢アルゎリズム, サンプリングアルゎリズム, タプルを展開しお関数呌び出しするapply関数, shared_ptrの配列察応, 最倧公玄数ず最小公倍数などが含たれる
Filesystem TS ファむルシステムのラむブラリ
Parallelism TS 䞊列ラむブラリ。<algorithm>や<numeric>に䞊列アルゎリズムが远加される

C++17以降、蚀語の策定にship train modelずいうリリヌス䜓制が蚭けられた。これは、3幎ごずの定期的な蚀語アップデヌトを提䟛するために、「仕様が完成したらリリヌス」ではなく「完成した仕様から順次リリヌスに含める」ずいう䜓制である。これにより、メゞャヌアップデヌトマむナヌアップデヌトずいうバヌゞョンアップはなくなった。

蚀語機胜

倉数・デヌタ構造関係

蚀語機胜 説明
16進浮動小数点数リテラル 十六進数衚蚘で浮動小数点数リテラルを蚘述できるようにする
むンラむン倉数 inline指定をするこずで翻蚳単䜍を跚いでひず぀のオブゞェクトになる倉数を定矩する
構造化束瞛 組・タプル・配列を展開しお倉数定矩する
単䞀芁玠の波カッコ初期化を非配列ずする 波カッコ初期化子が単䞀芁玠の堎合は T に掚論耇数芁玠の堎合は䞍適栌
[[maybe_unused]]属性 䜿甚しない可胜性のある倉数に察する譊告を抑制する
[[nodiscard]]属性 戻り倀を捚おおはならないこずを指定する
倀のコピヌ省略を保蚌 右蟺倀を倉数の初期化のために䜿甚する堎合、コピヌもムヌブも省略するこずを保蚌
厳密な匏の評䟡順 匏の評䟡順を芏定する
参照メンバをも぀クラスの眮き換え 参照型メンバやconstメンバ倉数を含むクラスに぀いおこれたで未定矩動䜜ずされおいた配眮newによるオブゞェクトの眮き換えを条件付きで可胜ずする
enum class倉数の初期倀ずしお敎数を指定する際の芏則を調敎 キャストを䜿甚するこずなく敎数を初期倀ずしお䜿甚し、E e{0};のような初期化を蚱可
アラむメント指定されたデヌタの動的メモリ確保 operator newずoperator deleteでアラむメント倀を取埗できるようにする
基底クラスのメンバ倉数を集成䜓初期化するための波カッコを省略できるようにする 基底クラスのメンバを集成䜓初期化するために、 derived d {{42}}; の代わりに derived d {42}; ず曞けるようにする

制埡構文

蚀語機胜 説明
if文ずswitch文の条件匏ず初期化を分離 if (init; condition)のように初期化ず条件匏を分けお蚘述できるようにする
[[fallthrough]]属性 フォヌルスルヌ時の譊告を抑制する
constexpr if文 if constexpr(cond)ずするこずで、そのif文はコンパむル時に凊理される
範囲for文のむテレヌタ型が䞀臎しないこずを蚱可 範囲 for 文の begin() ず end() が異なるむテレヌタ型を返せるようにするこずで、終端むテレヌタを定矩しやすくする

ラムダ匏

蚀語機胜 説明
ラムダ匏での*thisのコピヌキャプチャ キャプチャリストに*thisを指定するこずで、*thisをコピヌキャプチャする
constexprラムダ ラムダ匏の関数オブゞェクトが定数匏の文脈で䜿甚された堎合に、それがコンパむル時に評䟡されるようにする

テンプレヌト

蚀語機胜 説明
畳み蟌み匏 パラメヌタパックに察する二項挔算の环積凊理
テンプレヌトテンプレヌトパラメヌタにtypenameキヌワヌドの䜿甚を蚱可 classキヌワヌドしか䜿甚できなかった郚分に、typenameを蚱可する
クラステンプレヌトのテンプレヌト匕数掚論 コンストラクタの匕数からクラスのテンプレヌト匕数を掚論できるようにする
非型テンプレヌトパラメヌタのauto宣蚀 template <auto x>ずするこずで、X<3>; X<true>; X<'a'>のように定数を受け取りやすくする
党おの非型テンプレヌト匕数の定数匏評䟡を蚱可 ポむンタの定数匏評䟡ずしお、配列からポむンタぞの倉換や、関数から関数ポむンタぞの倉換などを蚱可
using宣蚀のパック展開 パラメヌタパックの型を基底クラスずしお指定した堎合に、using宣蚀に基底クラスのパラメヌタパックを指定できるようにする
倉数テンプレヌトのデフォルトテンプレヌト匕数を蚱可 倉数テンプレヌトのテンプレヌトパラメヌタがデフォルト匕数を持぀こずを蚱可する

定数匏

蚀語機胜 説明
static_assertのメッセヌゞ省略を蚱可 第2匕数だった蚺断メッセヌゞの省略を蚱可する
constexprラムダ ラムダ匏の関数オブゞェクトが定数匏の文脈で䜿甚された堎合に、それがコンパむル時に評䟡されるようにする
if constexpr文 if constexpr(cond)ずするこずで、そのif文はコンパむル時に凊理される

名前空間

蚀語機胜 説明
入れ子名前空間の定矩 namespace A::B {}のように、入れ子の名前空間を簡単に定矩できるようにする
名前空間ず列挙子ぞの属性付加を蚱可 名前空間の定矩ず、列挙型の各芁玠の定矩に、属性を付けられるようにする
using宣蚀のパック展開 パラメヌタパックの型を基底クラスずしお指定した堎合に、using宣蚀に基底クラスのパラメヌタパックを指定できるようにする

䟋倖

蚀語機胜 説明
䟋倖仕様を型システムの䞀郚にする 関数の型に䟋倖仕様が含たれるようにする
非掚奚だった叀い䟋倖仕様を削陀 throwキヌワヌドによる䟋倖仕様を削陀。throw()は残る

属性

蚀語機胜 説明
[[fallthrough]]属性 フォヌルスルヌ時の譊告を抑制する
[[maybe_unused]]属性 䜿甚しない可胜性のある倉数に察する譊告を抑制する
[[nodiscard]]属性 戻り倀を捚おおはならないこずを指定する
名前空間ず列挙子ぞの属性付加を蚱可 名前空間の定矩ず、列挙型の各芁玠の定矩に、属性を付けられるようにする
属性の名前空間指定に繰り返しをなくす [[using CC: opt(1), debug]]のように属性の名前空間宣蚀をたずめお行う
䞍明な属性を無芖する 実装が知らない名前空間の属性は無芖する

プリプロセッサ

蚀語機胜 説明
__has_include むンクルヌドするファむルが存圚するかを確認する

機胜の削陀

蚀語機胜 説明
トラむグラフの削陀 珟代では䜿甚する必芁がなくなったトラむグラフ機胜を削陀
非掚奚だったregisterキヌワヌドを削陀 コンパむラから単に無芖されおいたregisterキヌワヌドを削陀。予玄語は残る
非掚奚だったbool型に察するむンクリメント挔算子を削陀 bool倉数に察しお++するずtrueになる仕様を削陀
非掚奚だった叀い䟋倖仕様を削陀 throwキヌワヌドによる䟋倖仕様を削陀。throw()は残る

小さな倉曎

ここでは、コア蚀語䜜業グルヌプぞ問題報告され、その解決策ずしお導入された蚀語仕様の倉曎を解説する。

蚀語機胜 説明
曎新された定矩枈みマクロ 暙準芏栌で定矩されたマクロの曎新
機胜テストマクロ C++17 の機胜がサポヌトされおいるかどうかをテストするためのマクロ
noexcept付きのラムダ匏から倉換する関数ポむンタにnoexceptを付加する キャプチャを持たない非ゞェネリックラムダにnoexceptを付加した堎合、倉換した関数ポむンタにnoexceptを付加する
UTF-8文字リテラル UTF-8の指定が文字列リテラルに察しおしかできなかったが、文字リテラルにもUTF-8指定をできるようにする

ラむブラリ曎新の抂芁

新ラむブラリ

  • <filesystem>ヘッダを新蚭し、ファむルシステムラむブラリを远加。ファむル、ディレクトリなどを扱う
  • <algorithm>や<numeric>のアルゎリズムに、䞊列実行のオプションを远加
  • <optional>ヘッダを新蚭し、統䞀的な有効倀ず無効倀の衚珟をも぀optionalクラスを远加
  • <variant>ヘッダを新蚭し、型安党な共甚䜓variantクラスを远加
  • <any>ヘッダを新蚭し、なんでも代入できるanyクラスを远加
  • 暙準ラむブラリの参照をC11に曎新
    • <cfloat>に、非正芏化数の有無を刀定するマクロ、10進数の桁数を衚すマクロ、正の最小数を衚すマクロを远加
    • <cstdlib>に、aligned_alloc()関数を远加
    • <ctime>に、TIME_UTCマクロ, timespec構造䜓, timespec_get()関数を远加
    • <cstdio>に、vfscanf()関数を远加
    • <ccomplex>, <cstdalign>, <cstdbool>, <ctgmath>を非掚奚化

コンテナ

  • コンテナのコピヌ・ムヌブ、swap操䜜にnoexceptを远加
  • コンテナの芁玠情報にアクセスする非メンバ関数ずしお、<iterator>に size(), empty(), data()関数を远加
  • コンテナに䞍完党型の最小サポヌトを远加。vector, list, forward_listの芁玠型に、䞍完党型の指定を蚱可。ただし、これらのコンテナのなんらかのメンバ関数を呌び出す前には、芁玠型が完党型になっおいるこず
  • 倚盞アロケヌタずメモリプヌル。<memory_resource>が新蚭され、アロケヌトする型を芏定しないアロケヌタず、それを利甚したメモリプヌルの仕組みが導入される
  • 暙準むテレヌタ党般ずarrayの倉曎操䜜にconstexprを远加
  • emplace_front()ずemplace_back()メンバ関数で、远加された芁玠を返すようにする
  • 連想コンテナの接合機胜を远加。ほかのコンテナに芁玠を移すために抜出するextract()メンバ関数、抜出された芁玠をほかのコンテナに移すためのinsert()メンバ関数のオヌバヌロヌド、2぀の連想コンテナをたるごず接合するmerge()メンバ関数を远加
  • mapずunordered_mapに、挿入倱敗時の動䜜を芏定した新たなメンバ関数ずしお、try_emplace()ずinsert_or_assign()を远加
  • むテレヌタの分類に「隣接むテレヌタ (contiguous iterator)」を远加。芁玠間のメモリが隣接しおいるこずを衚す。以䞋のコンテナのむテレヌタは、隣接むテレヌタであるこずが芏定される
    • basic_string
    • array
    • bool以倖を芁玠型ずするvector
    • valarray (の非メンバ関数であるstd::begin()、std::end()で返されるむテレヌタは隣接むテレヌタ)

アルゎリズム

  • ランダムサンプリングアルゎリズムずしお、sample()を远加
  • 䞊列アルゎリズムの远加にずもない、<algorithm>にfor_each_n()を远加
  • 䞊列アルゎリズムの远加にずもない、<numeric>に以䞋を远加
    • accumulate()の蚈算順序を芏定しないバヌゞョンである、reduce()を远加
    • 郚分和を求める関数partial_sum()を、i番目の郚分和を求める際にi番目の芁玠を含める・含めないで分割し、inclusive_scan()ずexclusive_scan()を远加
    • 倀を倉換しながら畳み蟌むtransform_reduce()を远加
    • 倀を倉換しながら郚分和を求める関数ずしお、transform_inclusive_scan()ずtransform_exclusive_scan()を远加
  • 倀を範囲内に収めるclamp()関数を远加
  • boolを返す関数オブゞェクトの結果を反転させるnot_fn()関数を远加
  • INVOKE芁件に埓った関数呌び出しをするinvoke()関数を远加
  • reference_wrapperがTriviallyCopyableであるこずを保蚌
  • オブゞェクトをconstにするas_const()関数を远加
  • 未初期化メモリのアルゎリズムず、デストラクタ呌び出しの関数ずしお、以䞋の関数を远加 destroy_at(), destroy(), destroy_n(), uninitialized_move(), uninitialized_move_n(), uninitialized_value_construct(), uninitialized_value_construct_n(), uninitialized_default_construct(), uninitialized_default_construct_n()

文字列

  • <string_view>ヘッダを新蚭し、所有暩を持たない文字列クラスであるbasic_string_viewを远加
  • basic_string::data()メンバ関数の非const版を远加
  • 文字列怜玢アルゎリズムずしお、「ボむダヌ・ムヌア法 (Boyer-Moore)」のstd::boyer_moore_searcher関数オブゞェクトず「ボむダヌ・ムヌア・ホヌスプヌル法 (Boyer-Moore-Horspool)」のstd::boyer_moore_horspool_searcher関数オブゞェクトを远加。std::search()関数のポリシヌずしお、怜玢アルゎリズムを指定する
  • ロケヌル䟝存なし、フォヌマット解析なしの高速な文字列・数倀倉換関数ずしお、to_chars()ずfrom_chars()を远加
  • char_traitsクラスをconstexprに察応
  • バむトデヌタを衚すbyte型を远加

䞊行凊理

  • タむムアりト機胜がないReaders-writer lockのミュヌテックスずしお、shared_mutexクラスを远加
  • スコヌプ付きロックの可倉匕数版ずしお、scoped_lockクラスを远加
  • atomicクラスに、指定された芁玠型に察するアトミック操䜜がロックフリヌ(非ミュヌテックス)に振る舞うかを刀定するためにis_always_lock_free定数を远加
  • false sharingずtrue sharingを制埡するための機胜ずしお、hardware_destructive_interference_size定数ず、hardware_constructive_interference_size定数を远加

スマヌトポむンタ

  • shared_ptrを配列に察応
  • shared_ptrクラスに、指定された芁玠型のweak_ptr型を衚すweak_typeメンバ型を远加
  • shared_ptr::use_count()の仕様を明確化
  • shared_from_thisの指す先が曞き換わらないこずを芏定
  • 配列版unique_ptrの型倉換ずしお、以䞋のコヌドが䞍適栌だった

    std::unique_ptr<Foo const * const []> ptr1(new Foo*[10]);
    Foo const * ptr = ptr1[9];
    

    • このようなコヌドが適栌になるよう、倉換コンストラクタず倉換代入挔算子を远加
  • unique_ptrのテンプレヌト代入挔算子に、䞍足しおいたSFINAEルヌルを远加

  • owner_lessで、任意の芁玠型を持぀shared_ptr同士を比范できるようにする

æ•°å­Š

タプル

  • タプルを展開しお関数呌び出しするapply()関数を远加
  • タプルを任意の型のオブゞェクトに倉換するmake_from_tuple()関数を远加
  • 初期化子リストからpairずtupleを構築しやすくするための改善ずしお、以䞋のコヌドが適栌になるようコンストラクタの仕様を調敎

    std::tuple<int, int> pixel_coordinates()
    {
      return {10, -15};  // コンパむル゚ラヌ
    }
    
    struct NonCopyable { NonCopyable(int); NonCopyable(const NonCopyable&) = delete; };
    
    std::pair<NonCopyable, double> pmd{42, 3.14}; // C++14ではコンパむル゚ラヌ
                                                  // C++17ではOK
    

型特性

  • 倀を返す型特性クラスのconstexpr倉数テンプレヌト版を远加。倉数テンプレヌト版は、末尟に_vが付く。vはvalue (倀) を意味する
  • 型特性クラスを定矩しやすくするために、void_tを远加
  • bool定数を衚すbool_constantを远加
  • コンパむル時条件の論理挔算のために、論理積であるconjunction、論理和であるdisjunction、吊定であるnegationを远加
  • swap可胜かを刀定する型特性クラスずしお、is_swappable_with、is_swappable、is_nothrow_swappable_with、is_nothrow_swappableを远加
  • 関数が呌び出し可胜かを刀定する型特性ずしお、is_invocable、is_invocable_r、is_nothrow_invocable、is_nothrow_invocable_rを远加
  • 自動的にハッシュ倀が求められる型かを刀定するためにhas_unique_object_representations型特性を远加
  • invoke()の远加にずもない、関数の戻り倀型を取埗する型特性invoke_resultを远加。これたでのresult_ofず違っお関数型のテンプレヌト匕数を䜿甚しないため、それによっお起こっおいた厄介な問題を回避する

時間挔算

  • durationの䞞め挔算ずしお、切り䞋げをするfloor()、切り䞊げをするceil()、最近接偶数ぞの䞞めをするround()、絶察倀を求めるabs()を远加
  • time_pointの䞞め挔算ずしお、切り䞋げをするfloor()、切り䞊げをするceil()、最近接偶数ぞの䞞めをするround()を远加
  • durationクラスずtime_pointクラスの倉曎操䜜をconstexprに察応

乱数

  • ランダムサンプリングアルゎリズムずしお、sample()を远加
  • 乱数甚語を倉曎。乱数生成噚の芁件に 「URNG (Uniform Random Number Generator, 䞀様乱数生成噚)」ずいう甚語を䜿甚しおいたが、䞀般的なURNGの甚語ずは異なり、C++の乱数生成噚は䞀床の呌び出しで、(32ビットを超えるような) より倚くのビットを単䞀の笊号なし敎数にパックしお返すずいう動䜜が蚱可されおいる。動䜜の誀解を避けるために、「URBG (Uniform Random Bit Generator)」ずいう甚語に倉曎する

゚ラヌハンドリング

取り決め

  • std + 数字の名前空間を予玄。C++の今埌のバヌゞョンアップで暙準ラむブラリに倧きな倉曎を加えるずきのために、「std + 数字」 (正芏衚珟ではstd\d*) の名前空間が予玄される

機胜の削陀

  • 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クラスの別名型が削陀されるこずにずもない、それらの型をパラメヌタにずる関数が削陀

機胜の非掚奚化

  • 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_negateクラス
    • 暙準関数オブゞェクトの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()を非掚奚化

参照