cppreference.comsize_t
によると、いくつかのヘッダーで定義されています。
<cstddef>
<cstdio>
<cstring>
<ctime>
また、C++ 11以降では、
<cstdlib>
<cwchar>
まず第一に、なぜそうなのか疑問に思います。これは DRY の原則と矛盾していませんか?しかし、私の質問は次のとおりです。
size_t
を使用するには、上記のヘッダーのいずれを含める必要がありますか?それはまったく問題ですか?
インポートする関数と型を最小限に抑えたい場合、関数を宣言せず、6つの型しか宣言しないため、cstddef
を使用します。その他は、あなたにとって重要ではない特定のドメイン(文字列、時間、IO)に焦点を合わせます。
cstddef
はstd::size_t
の定義のみを保証することに注意してください。つまり、名前空間std
でsize_t
を定義しますが、mayグローバル名前空間(事実上、プレーンsize_t
)。
対照的に、stddef.h
(Cでも使用可能なヘッダー)は、グローバル名前空間でsize_t
を定義することを保証し、mayもstd::size_t
を提供します。
すべての標準ライブラリヘッダーファイルの定義は同じです。どちらを自分のコードに含めるかは関係ありません。私のコンピューターでは、_stddef.h
に次の宣言があります。このファイルは、リストしたすべてのファイルに含まれています。
/*
Define the size_t type in the std namespace if in C++ or globally if in C.
If we're in C++, make the _SIZE_T macro expand to std::size_t
*/
#if !defined(_SIZE_T) && !defined(_SIZE_T_DEFINED)
# define _SIZE_T_DEFINED
#if defined(_WIN64)
typedef unsigned __int64 size_t;
#else
typedef unsigned int size_t;
#endif
# if defined(__cplusplus)
# define _SIZE_T std::size_t
# else
# define _SIZE_T size_t
# endif
#endif
あなたはヘッダーなしで行うことができます:
using size_t = decltype(sizeof(int));
using size_t = decltype(sizeof 1); // The shortest is my favourite.
using size_t = decltype(sizeof "anything");
これは、C++標準が以下を必要とするためです。
sizeof
とsizeof...
の結果は、std::size_t
型の定数です。 [注:std::size_t
は、標準ヘッダー<cstddef>
(18.2)で定義されています。 —終了ノート]
言い換えれば、この規格には以下が必要です。
static_assert(std::is_same<decltype(sizeof(int)), std::size_t>::value,
"This never fails.");
また、同じtypedef-nameの他のすべてのtypedef
宣言と一致する限り、このstd
宣言をグローバルおよびtypedef
名前空間で作成しても問題ありません。一致しない宣言)。
それの訳は:
§7.1.3.1typedef-nameは、クラス宣言(9.1)またはenum宣言のように新しい型を導入しません。
§7.1.3.3特定の非クラススコープでは、typedef
指定子を使用して、そのスコープで宣言されている型の名前を再定義して、既に参照している型を参照できます。
これは名前空間std
に新しい型を追加するものであり、そのような行為は規格によって明示的に禁止されていると言う懐疑論者にとって、これはUBであり、それだけです。この態度は、根底にある問題のより深い理解を無視し、否定することに等しいと言わざるを得ません。
標準は、新しい宣言と定義を名前空間std
に追加することを禁止します。これにより、ユーザーが標準ライブラリを台無しにして、自分の足を完全に撃ち落とす可能性があるためです。標準的なライターにとっては、ユーザーがしてはならないすべてのことを禁止し、重要な何か(およびその脚)を逃す危険を冒すよりも、ユーザーにいくつかの特定のことを専門にさせ、適切な手段で他のことを禁止する方が簡単でした。彼らは過去に、標準コンテナを不完全な型でインスタンス化することを要求していなかったが、実際にはいくつかのコンテナがうまくいくかもしれない( 標準ライブラリアン:Matthew H. Austernによる不完全な型のコンテナ)を参照 ):
...結局、すべてが暗すぎて、あまり理解されていないように見えました。標準化委員会は、STLコンテナは不完全な型で動作するはずがないと言う以外に選択肢はないと考えていました。適切な対策として、標準ライブラリの残りにもその禁止を適用しました。
...振り返ってみると、テクノロジーの理解が深まった今でも、その決定は基本的に正しいようです。はい、場合によっては、いくつかの標準コンテナを実装して、不完全な型でインスタンス化できるようにすることが可能ですが、他のケースでは困難または不可能になることも明らかです。ほとんどの場合、
std::vector
を使用した最初のテストが偶然簡単なケースの1つである可能性がありました。
言語規則がstd::size_t
が正確にdecltype(sizeof(int))
である必要があることを考えると、namespace std { using size_t = decltype(sizeof(int)); }
を実行することは何も壊さないことの1つです。
C++ 11より前のバージョンではdecltype
がなかったため、sizeof
の型を宣言する方法は、テンプレートを大量に取得することなく1つの単純なステートメントになりました。 size_t
は異なるターゲットアーキテクチャで異なる型をエイリアスしますが、sizeof
の結果のためだけに新しい組み込み型を追加するのはエレガントなソリューションではなく、標準の組み込みtypedefはありません。したがって、当時の最も移植性の高いソリューションは、特定のヘッダーにsize_t
タイプエイリアスを挿入し、それを文書化することでした。
C++ 11には、標準の厳密な要件を1つの単純な宣言として書き留める方法があります。