C++標準ライブラリ
C++標準ライブラリは、標準C++で使用できる幅広い機能を提供します。
目次 |
[編集] カテゴリ
言語サポートライブラリは、メモリ割り当て (new/delete) や例外処理など、C++言語の特定の部分で必要とされるコンポーネントを提供します。
|
コンセプトライブラリは、C++プログラムがテンプレート引数のコンパイル時検証や、型のプロパティに基づいた関数ディスパッチを行うために使用できるライブラリコンポーネントを記述します。 |
(C++20以降) |
診断ライブラリは、事前定義された例外クラスを含め、C++プログラムでのエラー報告のための一貫したフレームワークを提供します。
メモリ管理ライブラリは、スマートポインタやスコープ付きアロケータ(C++11から)など、メモリ管理のためのコンポーネントを提供します。
|
メタプログラミングライブラリは、型特性、整数シーケンス、(C++14から)および有理数演算を含め、テンプレートや定数評価中に使用するための機能を記述します。 |
(C++11以降) |
汎用ユーティリティライブラリには、動的ストレージ管理のための事前定義されたストレージアロケータなど、他のライブラリ要素で使用されるコンポーネントや、タプルや(C++11から)関数ラッパーなど、C++プログラムの基盤として使用されるコンポーネントが含まれます。
コンテナ、イテレータ、範囲(C++20から)、およびアルゴリズムライブラリは、C++プログラムに、最も広く使用されているアルゴリズムとデータ構造のサブセットへのアクセスを提供します。
文字列ライブラリは、char、char8_t(C++20から)、char16_t、char32_t(C++11から)、wchar_t、およびその他の文字様型といった、均質なシーケンスとして表現されるテキストを操作するためのサポートを提供します。
テキスト処理ライブラリは、正規表現のマッチングと検索(C++11から)、テキストフォーマット用のユーティリティ(C++20から)およびテキストエンコーディングの識別(C++26から)、そしてローカライズ機能を提供します。
数値ライブラリは、数値処理のサポートを拡張する数値アルゴリズムと複素数コンポーネントを提供します。valarrayコンポーネントは、そのような処理をサポートするプラットフォーム上で並列操作として実装される可能性のある、n-at-a-time処理のサポートを提供します。乱数コンポーネントは、擬似乱数を生成するための機能を提供します。(C++11から)
時間ライブラリは、一般的に役立つ時間ユーティリティを提供します。
入出力ライブラリは、C++プログラムの入出力の主要なメカニズムであるiostreamコンポーネントを提供します。これらは、特に文字列、ロケール、イテレータといったライブラリの他の要素と共に使用できます。
|
スレッドサポートライブラリは、アトミック操作、相互排他、およびスレッド間通信を含む、スレッドを作成および管理するためのコンポーネントを提供します。 |
(C++11以降) |
|
実行サポートライブラリは、汎用実行リソース上での非同期実行を管理するためのフレームワークを提供します。 |
(C++26以降) |
[編集] ライブラリの内容
C++標準ライブラリは、特に指定がない限り、C++標準ライブラリヘッダの概要で説明されているエンティティとマクロの定義を提供します。
operator newとoperator deleteを除くすべてのライブラリエンティティは、名前空間stdまたは名前空間std内にネストされた名前空間内で定義されます(C標準ライブラリ機能のエンティティを除く、下記参照)。特定の名前空間で宣言された名前が、その名前空間で直接宣言されるか、その名前空間内のインライン名前空間で宣言されるかは未規定です。(C++11から)
[編集] ヘッダ
C++標準ライブラリの各要素は、(適切に)ヘッダで宣言または定義されます。ヘッダは必ずしもソースファイルである必要はなく、ヘッダ名内の<と>で区切られたシーケンスも、必ずしも有効なソースファイル名である必要はありません。
C++標準ライブラリは、C++ライブラリヘッダとCライブラリ機能用の追加C++ヘッダを提供します(説明については「ヘッダ」ページを参照)。
| Cライブラリ機能のためのC++ヘッダ | ||||
|---|---|---|---|---|
| <cassert> | <clocale> | <cstdarg> | <cstring> | |
| <cctype> | <cmath> | <cstddef> | <ctime> | |
| <cerrno> | <csetjmp> | <cstdio> | <cwchar> | |
| <cfloat> | <csignal> | <cstdlib> | <cwctype> | |
| <climits> | ||||
| C++11で追加されたヘッダ | ||||
| <cfenv> | <cinttypes> | <cstdint> | <cuchar> | |
| 削除されたヘッダ | ||||
| <ccomplex> | (C++11から)(C++17で非推奨)(C++20で削除) | |||
| <ciso646> | (C++20で削除) | |||
| <cstdalign> | (C++11から)(C++17で非推奨)(C++20で削除) | |||
| <cstdbool> | (C++11から)(C++17で非推奨)(C++20で削除) | |||
| <ctgmath> | (C++11から)(C++17で非推奨)(C++20で削除) | |||
フリースタンディング実装は、実装定義のヘッダセットを持ちます。ヘッダセットの最小要件についてはこちらを参照してください。
[編集] C標準ライブラリ
C++標準ライブラリは、静的な型安全性を保証するように適切に調整されたC標準ライブラリの機能も利用可能にします。多くのライブラリ関数の説明は、それらの関数のセマンティクスについてC標準ライブラリに依存しています。
場合によっては、標準C++で規定されたシグネチャがC標準ライブラリのシグネチャと異なることがあり、追加のオーバーロードが宣言されることもありますが、特に明記されていない限り、動作と事前条件(Cのrestrictによって暗示されるものを含む)(C++17から)は同じです。
C標準ライブラリとの互換性のために、C++標準ライブラリは以下にリストされているCヘッダを提供します。これらのヘッダの使用目的は、相互運用性のためだけです。C++ソースファイルが有効なISO Cであるために、これらのヘッダのいずれかをインクルードする必要がある場合があります。有効なISO Cでもあることを意図していないソースファイルは、Cヘッダを使用すべきではありません。説明についてはこちらを参照してください。
| Cヘッダ | |||
|---|---|---|---|
| <assert.h> | <limits.h> | <stdarg.h> | <string.h> |
| <ctype.h> | <locale.h> | <stddef.h> | <time.h> |
| <errno.h> | <math.h> | <stdio.h> | <wchar.h> |
| <float.h> | <setjmp.h> | <stdlib.h> | <wctype.h> |
| <iso646.h> | <signal.h> | ||
| C++11で追加されたヘッダ | |||
| <complex.h> | <inttypes.h> | <stdbool.h> | <tgmath.h> |
| <fenv.h> | <stdalign.h> | <stdint.h> | <uchar.h> |
| C++23で追加されたヘッダ | |||
| <stdatomic.h> | |||
| C++26で追加されたヘッダ | |||
| <stdbit.h> | <stdchkint.h> | ||
特に明記されていない限り、各ヘッダcxxxの内容は、C標準ライブラリで規定されている対応するヘッダxxx.hの内容と同じです。ただし、C++標準ライブラリでは、宣言(Cでマクロとして定義されている名前を除く)は名前空間stdの名前空間スコープ内にあります。これらの名前(追加されたオーバーロードを含む)が最初にグローバル名前空間スコープ内で宣言され、その後明示的なusing宣言によって名前空間stdに注入されるかどうかは未規定です。
Cでマクロとして定義されている名前(assert, offsetof, setjmp, va_arg, va_end, va_start)は、Cが関数としての実装を許可していても、C++標準ライブラリではマクロとして定義されなければなりません。
Cで関数として定義されている名前は、C++標準ライブラリでも関数として定義されなければなりません。これにより、Cで許可されている、関数プロトタイプに加えてマスキングマクロを提供するという慣行は禁止されます。C++で同等のインライン動作を実現する唯一の方法は、extern inline関数として定義を提供することです。
C++のキーワードまたは演算子である識別子は、C++標準ライブラリヘッダでマクロとして定義することはできません。特に、標準ヘッダ<iso646.h>をインクルードしても何の効果もありません。
[編集] 標準Cの安全な関数に関連付けられた名前 (C++17から)
いずれかのC++ヘッダがインクルードされた場合、以下のC標準Annex Kの名前のいずれかがグローバル名前空間で宣言されるかどうかは実装定義です(これらのうち、名前空間stdで宣言されるものはありません)。
[編集] ライブラリの使用
[編集] ヘッダのインクルード
C++標準ライブラリのエンティティはヘッダで定義されており、その内容は、適切な #includeプリプロセッシングディレクティブを含む翻訳単位で利用可能になります。
翻訳単位はライブラリヘッダを任意の順序でインクルードできます。各ヘッダは複数回インクルードできますが、ちょうど1回インクルードした場合と異なる効果はありません。ただし、<cassert>または<assert.h>をインクルードする効果は、その都度、語彙的に現在のNDEBUGの定義に依存します。
翻訳単位は、いかなる宣言や定義の外側で、かつその翻訳単位内でそのヘッダに宣言されているエンティティへの最初の参照よりも語彙的に前に、ヘッダをインクルードすることしかできません。診断は要求されません。
|
モジュールユニットでは、ヘッダはグローバルモジュールフラグメント内でのみインクルードできます。 |
(C++20以降) |
ヘッダのインポートC++ライブラリヘッダ、またはフリースタンディング実装の場合は実装が提供するそのようなヘッダのサブセットは、集合的にインポート可能なC++ライブラリヘッダとして知られています。 インポート可能なC++ライブラリヘッダの内容は、適切なimport宣言を含む翻訳単位で利用可能になります。 |
(C++20以降) |
モジュールのインポートC++標準ライブラリは、以下のC++ライブラリモジュールを提供します。
標準ライブラリの各宣言について、 |
(C++23から) |
[編集] リンケージ
C++標準ライブラリのエンティティはstorage duration#external linkage(外部リンケージ)を持ちます。特に指定がない限り、オブジェクトと関数はデフォルトのextern "C++" リンケージを持ちます。
外部リンケージで宣言されたC標準ライブラリの名前がextern "C"またはextern "C++"リンケージを持つかは実装定義です。C++標準では、この場合にextern "C++"を使用することが推奨されています。
ライブラリで定義され、C++プログラムで必要とされるオブジェクトと関数は、プログラムの開始前にプログラムにインクルードされます。
[編集] 標準ライブラリ実装への要求事項
[編集] 保証
C++ヘッダは、以下に現れる宣言と定義を提供しなければなりません。
- そのヘッダの概要、または
- そのヘッダの概要に含まれているように見える別のヘッダの概要。
複数のヘッダで定義されている型やマクロ(NULLなど)について、これらのヘッダを任意の数、任意の順序でインクルードしても、ODR (One Definition Rule)に違反することはありません。
特に指定がない限り、C標準ライブラリによって定義され、整数定数式に展開されるすべてのオブジェクト形式マクロは、#ifプリプロセッシングディレクティブで使用できます。
標準ライブラリの非メンバ関数シグネチャを呼び出すと、常に実際にその関数が呼び出されます。したがって、適合する標準ライブラリ実装は、有効なC++プログラムによって呼び出される可能性のある追加の非メンバ関数を定義することはできません。
非メンバ関数シグネチャは、追加のデフォルト引数付きで宣言されることはありません。
特に指定がない限り、標準ライブラリの関数から非演算子、非メンバ関数への呼び出しは、実引数依存の名前探索によって見つかる別の名前空間の関数を使用しません。
クラス(テンプレート)定義内の関数(テンプレート)の各フレンド宣言について、その関数(テンプレート)に対する他の宣言は提供されません。
|
標準ライブラリの関数シグネチャは、constexprであることが要求される場合にのみconstexprとして宣言できます(libstdc++のcmathはここで特に非準拠です)。ヘッダがconstexpr関数またはコンストラクタの非定義宣言を提供する場合、対応する定義もそのヘッダ内で提供されるべきです。 データ競合を防ぐため、特に指定がない限り、各標準ライブラリ関数は以下の各要件を満たすべきです。
|
(C++11以降) |
C++標準ライブラリで定義された別のクラスから派生することが要求される、C++標準ライブラリで定義された各クラスについて、
- 基底クラスは、virtualとして指定されている場合は仮想でなければなりません。
- 基底クラスは、virtualとして指定されていない場合は仮想であってはいけません。そして
- 特に指定がない限り、異なる名前を持つ型は異なる型でなければなりません。
|
特に指定がない限り、C++標準ライブラリで規定されるすべての型は非final型です。 |
(C++11以降) |
C++標準ライブラリで定義された関数が、(特定の状況で)特定の型の例外をスローすると規定されている場合、スローされる例外はその型またはその型から派生した型のみを持つことができ、これにより基底型の例外ハンドラがそれをキャッチできます。
C標準ライブラリの関数は、プログラムが提供する関数が例外をスローする場合にのみ例外をスローできます(qsort()およびbsearch()がこの条件を満たします)。
C++標準ライブラリで定義されたデストラクタ操作は、決して例外をスローしません。C++標準ライブラリのすべてのデストラクタは、非スロー例外指定を持っているかのように振る舞います。
|
C++標準ライブラリの関数がstd::error_codeオブジェクトを介してエラーを報告する場合、オペレーティングシステムに起因するエラーについてはそのオブジェクトのcategory()メンバがstd::system_category()を返し、他の場所に起因するエラーについては実装定義のstd::error_categoryオブジェクトへの参照を返さなければなりません。これらの各エラーカテゴリに対するvalue()の可能な値は定義されるべきです。 C++標準ライブラリで定義された型のオブジェクトは、ムーブ元になることができます。ムーブ操作は明示的に指定されるか、暗黙的に生成されます。特に指定がない限り、そのようなムーブ元オブジェクトは有効だが未規定の状態に置かれます。 C++標準ライブラリで定義された型のオブジェクトは、それ自身にムーブ代入されることがあります。特に指定がない限り、そのような代入はオブジェクトを有効だが未規定の状態に置きます。 |
(C++11以降) |
[編集] 実装の自由度
C++標準ライブラリのメンバ関数または非メンバ関数がinlineとして定義されるかどうかは未規定です。
非仮想のC++標準ライブラリメンバ関数について、与えられた宣言セットからオーバーロードを選択するようなそのメンバ関数への呼び出しが、そのオーバーロードが選択されたかのように振る舞う限り、異なるメンバ関数シグネチャのセットを宣言することができます。これにより、例えば以下が可能になります。
- デフォルト引数付きのパラメータを追加する、
- デフォルト引数付きのメンバ関数を、同等の振る舞いを持つ2つ以上のメンバ関数で置き換える、または
- メンバ関数名に追加のシグネチャを追加する。
特に指定がない限り、C++標準ライブラリのどの関数が再帰的に再入可能かは実装定義です。
|
C++標準ライブラリ実装は、ユーザに可視でなく、データ競合から保護されている限り、自身の内部オブジェクトをスレッド間で共有できます。 |
(C++11以降) |
C++標準ライブラリの関数シグネチャまたはクラスが、C++標準ライブラリの別のクラスのフレンドであるかどうかは未規定です。
ここで説明されている名前とグローバル関数シグネチャは、実装に予約されています。
C++標準ライブラリのどのクラスも、実装に予約された名前を持つクラスから派生することができます。C++標準ライブラリで定義されたクラスがC++標準ライブラリの他のクラスから派生することが要求される場合、そのクラスは要求された基底から直接、または実装に予約された名前を持つ基底クラスの階層を通じて間接的に派生することができます。
C++標準ライブラリで定義された関数が例外をスローすると規定されていないが、非スロー例外指定を持たない場合、スローされる例外は実装定義ですが、その型はstd::exceptionまたはstd::exceptionから派生した型であるべきです。
非仮想関数の例外指定は、非スロー例外指定を追加することで強化できます。
[編集] ノート
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_lib_modules |
202207L |
(C++23) | 標準ライブラリモジュール std と std.compat |
[編集] 欠陥報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 1 | C++98 | C標準ライブラリからの名前の言語リンケージが未規定だった 未規定だった |
現在は 実装定義 |
| LWG 119 | C++98 | 仮想関数の例外指定が強化される可能性があった 可能性があった |
非仮想関数でのみ 許可されるようになった |
| LWG 147 | C++98 | 非メンバ関数に関する規定がグローバル関数のみを考慮していた 考慮していた |
非グローバル関数も 考慮するようになった |
| LWG 225 | C++98 | 標準ライブラリ関数が実引数依存の探索により他の名前空間の非メンバ関数を呼び出す可能性があった 可能性があった |
特に指定がない限り 禁止された |
| LWG 336 | C++98 | <strstream>がC++ライブラリヘッダではなかった | C++ライブラリヘッダであるとされた |
| LWG 343 | C++98 | ライブラリヘッダの依存関係が規定されていなかった | 規定された(概要に記載) |
| LWG 456 | C++98 | Cライブラリ機能のためのC++ヘッダは名前空間stdでのみ定義を提供できた できた |
グローバル名前空間で定義し、 その後名前空間stdに注入することが許可された |
| LWG 465 | C++98 | C++のキーワードまたは演算子である識別子がC++標準ライブラリヘッダでマクロとして定義される可能性があった 可能性があった (<ciso646>のみがマクロとして定義しないことが要求されていた) |
すべてのC++標準 ライブラリヘッダで マクロとして定義できなくなった |
| LWG 1178 | C++98 | C++ヘッダは必要な定義を含むC++ヘッダをインクルードしなければならなかった ならなかった |
C++ヘッダは、その概要に直接または 間接的に含まれる宣言と 定義を提供しなければならないとされた |
| LWG 2013 | C++11 | 標準でconstexprであることが要求されない関数が、標準ライブラリによってconstexprとして宣言できるかどうかが未規定だった 未規定だった 宣言できないとされた |
禁止された |
| LWG 2225 | C++98 | ヘッダが不正な位置でインクルードされた場合に診断が要求されていた 要求されていた |
この場合に診断は 要求されなくなった |