Type
Objects 、 references 、 functions ( function template specializations を含む)、および expressions は type と呼ばれる特性を持ち、これらエンティティに対して許可される操作を制限するとともに、本来は汎用的なビット列に意味論的な意味を与えます。
目次 |
型分類
C++の型システムは以下の型で構成されています:
- 基本型 (関連項目: std::is_fundamental ):
-
- 型 void (関連項目: std::is_void );
|
(C++11以降) |
-
- 算術型 (関連項目: std::is_arithmetic ):
-
- 整数型 ( cv修飾版 を含む、関連項目: std::is_integral 、整数型の同義語は integral type):
-
- 型 bool ;
- 文字型:
-
- ナロー文字型:
-
- 通常文字型: char , signed char , unsigned char [1]
|
(C++20以降) |
-
-
-
-
- ワイド文字型: char16_t , char32_t , (C++11以降) wchar_t ;
- 符号付き整数型:
-
- 標準符号付き整数型: signed char , short , int , long , long long ;
-
-
-
|
(C++11以降) |
-
-
-
- 符号なし整数型:
-
- 標準符号なし整数型: unsigned char , unsigned short , unsigned , unsigned long , unsigned long long ;
-
-
|
(C++11以降) |
-
-
- 浮動小数点型(関連項目: std::is_floating_point ):
-
- 標準浮動小数点型: float , double , long double およびそれらの cv修飾版 ;
-
| (C++23以降) |
- 複合型(関連項目: std::is_compound ):
-
- 参照型 (参照: std::is_reference ):
-
- 左辺値参照型 (参照: std::is_lvalue_reference ):
-
- オブジェクト型への左辺値参照;
- 関数型への左辺値参照;
|
(C++11以降) |
-
- ポインタ型 (参照: std::is_pointer ):
- メンバへのポインタ型 (参照: std::is_member_pointer ):
-
- データメンバへのポインタ 型 (参照: std::is_member_object_pointer );
- メンバ関数へのポインタ 型 (参照: std::is_member_function_pointer );
- 配列型 (参照: std::is_array );
- 関数型 (参照: std::is_function );
- 列挙型 (参照: std::is_enum );
|
(C++11以降) |
`/`
`/`
-
-
- non-union types (参照: std::is_class );
- union types (参照: std::is_union ).
-
- ↑ signed char および unsigned char はナロウ文字型であるが、文字型ではない。言い換えれば、ナロウ文字型の集合は文字型の集合の部分集合ではない。
参照型および関数型以外のすべての非cv修飾型に対して、型システムはその型の3つの追加の cv修飾版 ( const 、 volatile 、および const volatile ) をサポートします。
その他のカテゴリ
object type ( std::is_object も参照)は、関数型でも参照型でもなく、また(CV修飾された可能性のある) void でもない(CV修飾された可能性のある)型です。
以下の型はまとめて スカラ型 と呼ばれます( std::is_scalar も参照してください):
| (C++11以降) |
- これらの型のCV修飾版
以下の型は総称して implicit-lifetime types と呼ばれます:
- scalar types
- implicit-lifetime class types
- array types
- cv-qualified versions of these types
|
以下の型は総称して トリビアリーコピー可能型 と呼ばれる:
以下の型は総称して スタンダードレイアウト型 と呼ばれる:
|
(C++11以降) |
| 型特性階層図 |
|---|
|
注記: SVG画像の要素はクリック可能ですが、まず新しいブラウザタブで図を開く必要があります |
非推奨カテゴリ
|
以下の型は総称して POD型 と呼ばれる (参照: std::is_pod ):
|
(C++20で非推奨) |
|
以下の型は総称して トリビアル型 と呼ばれる (参照: std::is_trivial ):
|
(C++11以降)
(C++26で非推奨) |
プログラム定義型
プログラム定義特殊化( program-defined specialization )は、C++ standard library の一部ではなく、実装によって定義されていない explicit specialization または partial specialization です。
プログラム定義型は以下のいずれかの型です:
- C++標準ライブラリの一部ではなく、実装によって定義されていない 非 closure (C++11以降) class type または enumeration type
|
(C++11以降) |
- プログラム定義の特殊化の インスタンス化 。
型命名
name は以下の方法で型を参照するように宣言できます:
- class 宣言;
- union 宣言;
- enum 宣言;
- typedef 宣言;
- type alias 宣言.
C++プログラムでは名前を持たない型を参照する必要がしばしば生じます。そのための構文は
type-id
として知られています。型
T
を命名するtype-idの構文は、型
T
の変数または関数の
宣言
構文から識別子を省略したものと正確に一致します。ただし、宣言文法の
decl-specifier-seq
は
type-specifier-seq
に制約され、また新しい型はtype-idが非テンプレートの型エイリアス宣言の右辺に現れる場合にのみ定義できます。
int* p; // intへのポインタの宣言 static_cast<int*>(p); // type-idは"int*" int a[3]; // 3つのintの配列の宣言 new int[3]; // type-idは"int[3]"(new-type-idと呼ばれる) int (*(*x[2])())[3]; // 3つのintの配列へのポインタを返す関数への // ポインタの配列(2要素)の宣言 new (int (*(*[2])())[3]); // type-idは"int (*(*[2])())[3]" void f(int); // intを受け取りvoidを返す関数の宣言 std::function<void(int)> x = f; // 型テンプレートパラメータはtype-id "void(int)" std::function<auto(int) -> void> y = f; // 同上 std::vector<int> v; // intのvectorの宣言 sizeof(std::vector<int>); // type-idは"std::vector<int>" struct { int x; } b; // 新しい型を作成し、その型のオブジェクトbを宣言 sizeof(struct { int x; }); // エラー:sizeof式内で新しい型を定義できない using t = struct { int x; }; // 新しい型を作成し、tをその型のエイリアスとして宣言 sizeof(static int); // エラー:ストレージクラス指定子は型指定子シーケンスの一部ではない std::function<inline void(int)> f; // エラー:関数指定子も同様に不可
宣言文法のうち名前が除去された declarator 部分は、 abstract-declarator と呼ばれます。
Type-idは以下の状況で使用されることがあります:
- キャスト式において対象の型を指定するため キャスト式 ;
-
以下の演算子・指定子の引数として
sizeof,alignof,alignas,new, およびtypeid; - 型エイリアス 宣言の右辺として;
- 関数 宣言の末尾戻り値型として;
- テンプレート型パラメータ のデフォルト引数として;
- テンプレート型パラメータ に対するテンプレート引数として;
|
(C++17まで) |
Type-idは以下の状況で一部変更を加えて使用することができます:
- 関数の パラメータリスト 内(パラメータ名が省略されている場合)、型IDは type-specifier-seq の代わりに decl-specifier-seq を使用する(特に、いくつかのストレージクラス指定子が許可される);
- ユーザー定義変換関数 の名前では、抽象宣言子に関数または配列演算子を含めることができない。
|
このセクションは不完全です
理由: 8.2[dcl.ambig.res] を簡潔に要約できる場合 |
|
このセクションは不完全です
理由: decltypeとautoについて言及しリンクを追加 |
詳細型指定子
詳細型指定子は、以前に宣言されたクラス名(class、struct、union)または列挙型名を参照するために使用できます。たとえその名前が 非型宣言によって隠蔽されていた場合でも 使用可能です。また、新しいクラス名を宣言するためにも使用できます。
詳細については elaborated type specifier を参照してください。
静的型
プログラムのコンパイル時解析によって得られる式の型は、 static type (静的型)として知られています。静的型はプログラムの実行中に変化しません。
動的型
何らかの glvalue expression が polymorphic object を参照する場合、その最も派生したオブジェクトの型はdynamic typeとして知られています。
// 与えられたもの struct B { virtual ~B() {} }; // ポリモーフィック型 struct D : B {}; // ポリモーフィック型 D d; // 最も派生したオブジェクト B* ptr = &d; // (*ptr)の静的型はB // (*ptr)の動的型はD
prvalue式の場合、動的型は常に静的型と同じです。
不完全型
以下の型は 不完全型 です:
- 型 void (場合によっては cv 修飾される可能性あり);
- 不完全定義オブジェクト型 :
その他のすべての型は完全型です。
以下のいずれかのコンテキストでは、型
T
が完全型である必要があります:
-
定義
または戻り値型
Tまたは引数型Tを持つ関数の呼び出し; -
定義
型
Tのオブジェクトの; -
型
Tの 非静的クラスデータメンバ の宣言; -
new式 型Tのオブジェクトまたは要素型がTである配列の; -
lvalue-to-rvalue変換
型
Tのglvalueに適用された; -
暗黙的
または
明示的
変換 型
Tへの; -
標準変換
,
dynamic_cast, またはstatic_cast型 T * または T & への, ヌルポインタ定数 からの変換または 修飾可能性のあるvoidへのポインタ からの変換を除く; -
クラスメンバアクセス演算子
型
Tの式に適用された; -
typeid,sizeof, またはalignof演算子 型Tに適用された; -
算術演算子
Tへのポインタに適用された; -
基底クラス
Tを持つクラスの定義; -
型
Tのlvalueへの代入; -
ハンドラ
型
T, T & , または T * の.
(一般的に、
T
のサイズとレイアウトを知る必要がある場合。)
これらの状況のいずれかが翻訳単位で発生する場合、その型の定義は同じ翻訳単位に現れなければなりません。そうでない場合は、必須ではありません。
不完全に定義されたオブジェクト型は完成させることができます:
- クラス型(例えば class X )は、翻訳単位内のある時点では不完全型として扱われ、後になって完全型として扱われることがある。型 class X は両方の時点で同じ型である:
struct X; // Xの宣言(定義はまだ提供されていない) extern X* xp; // xpは不完全型へのポインタ: // Xの定義は到達可能ではない void foo() { xp++; // 不正:Xは不完全型 } struct X { int i; }; // Xの定義 X x; // OK:Xの定義が到達可能 void bar() { xp = &x; // OK:型は「Xへのポインタ」 xp++; // OK:Xは完全型 }
- 配列オブジェクトの宣言された型は、不完全なクラス型の配列であり、したがって不完全である可能性があります。クラス型が翻訳単位の後半で完全化された場合、配列型は完全型になります。これら2つの時点における配列型は同じ型です。
-
配列オブジェクトの宣言された型は、未知のサイズの配列であり、したがって翻訳単位のある時点では不完全であり、後で完全になる可能性があります。これら2つの時点における配列型(「
Tの未知のサイズの配列」と「 NTの配列」)は異なる型です。
未知の境界を持つ配列へのポインタまたは参照の型は、恒久的に不完全な型を指す、または参照します。
typedef
宣言によって命名された未知の境界を持つ配列は、恒久的に不完全な型を参照します。いずれの場合も、配列型を完全にすることはできません:
extern int arr[]; // arrの型は不完全型 typedef int UNKA[]; // UNKAは不完全型 UNKA* arrp; // arrpは不完全型へのポインタ UNKA** arrpp; void foo() { arrp++; // エラー: UNKAは不完全型 arrpp++; // OK: UNKA*のサイズは既知 } int arr[10]; // ここでarrの型は完全型となる void bar() { arrp = &arr; // OK: 修飾変換 (C++20以降) arrp++; // エラー: UNKAは完全化できない }
不具合報告
以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| CWG 328 | C++98 |
不完全型のクラスメンバーは禁止されていなかった
クラス型のオブジェクトが作成されない場合 |
非静的クラスデータメンバーは
完全型である必要がある |
| CWG 977 | C++98 | 列挙型の定義内で完全型となる時点が不明確だった |
基底型が決定された時点で
型は完全となる |
| CWG 1362 | C++98 |
型
T*
または
T&
へのユーザー定義変換に
T
の完全性が必要だった
|
不要 |
| CWG 2006 | C++98 | cv修飾された void 型は オブジェクト型かつ完全型だった | 両方のカテゴリから除外 |
| CWG 2448 | C++98 | cv非修飾型のみが整数型および浮動小数点型になれた | cv修飾型を許可 |
| CWG 2630 | C++98 |
クラス定義が現れる翻訳単位の外側でクラスが
完全と見なされるか不明確だった |
この場合、クラス定義が
到達可能であればクラスは 完全型となる |
| CWG 2643 | C++98 |
未知の境界を持つ配列へのポインタの型は
完全化できなかった(しかし既に完全型である) |
指し示される配列型は
完全化できない |
| LWG 2139 | C++98 | 「ユーザー定義型」の意味が不明確だった |
「プログラム定義型」を
代わりに定義して使用 |
| LWG 3119 | C++11 | クロージャ型がプログラム定義型か不明確だった | 明確化された |
参考文献
- C++23規格 (ISO/IEC 14882:2024):
-
- 6.8.2 基本型 [basic.fundamental]
- C++20標準 (ISO/IEC 14882:2020):
-
- 6.8.2 基本型 [basic.fundamental]
- C++17規格 (ISO/IEC 14882:2017):
-
- 6.9.1 基本型 [basic.fundamental]
- C++14規格 (ISO/IEC 14882:2014):
-
- 3.9.1 基本型 [basic.fundamental]
- C++11標準 (ISO/IEC 14882:2011):
-
- 3.9.1 基本型 [basic.fundamental]
- C++98標準 (ISO/IEC 14882:1998):
-
- 3.9.1 基本型 [basic.fundamental]
関連項目
| Type traits | 型のプロパティを問い合わせるためのコンパイル時テンプレートベースのインターフェース |
|
C documentation
for
Type
|
|
外部リンク
| 1. | Howard HinnantのC++0x型階層 |