名前空間
変種
操作

From cppreference.com
< cpp‎ | language
 
 
C++言語
全般
フロー制御
条件実行文
if
繰り返し文 (ループ)
for
範囲for (C++11)
ジャンプ文
関数
関数宣言
ラムダ式
inline指定子
動的例外仕様 (C++17まで*)
noexcept指定子 (C++11)
例外
名前空間
指定子
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点数
文字 - 文字列 - nullptr (C++11)
ユーザー定義 (C++11)
ユーティリティ
属性 (C++11)
typedef宣言
型エイリアス宣言 (C++11)
キャスト
メモリ確保
クラス
クラス固有の関数プロパティ
explicit (C++11)
static

特殊メンバ関数
テンプレート
その他
 
 

オブジェクト参照関数関数テンプレートの特殊化を含む)、およびは、と呼ばれるプロパティを持ち、それはこれらのエンティティに許可される操作を制限し、そうでなければ汎用的なビットシーケンスに意味的意味を与えます。

目次

[編集] 型の分類

C++の型システムは以下の型から構成されます

(C++11以降)
  • bool
  • 文字型
  • 狭い文字型
  • 通常の文字型: char, signed char, unsigned char[1]
  • char8_t
(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以降)
  • 標準浮動小数点型: float, double, long double およびそれらのcv修飾版
(C++23から)
  • オブジェクト型への左辺値参照;
  • 関数型への左辺値参照;
  • オブジェクト型への右辺値参照;
  • 関数型への右辺値参照;
(C++11以降)
(C++11以降)
  1. signed charunsigned charは狭い文字型ですが、文字型ではありません。言い換えれば、狭い文字型の集合は文字型の集合の部分集合ではありません。

参照型と関数型以外のすべての非cv修飾型について、型システムはさらに3つのcv修飾版constvolatileconst volatile)をサポートします。

[編集] その他のカテゴリ

オブジェクト型std::is_objectも参照)は、関数型でも参照型でもなく、(cv修飾されている可能性のある)voidでもない、(cv修飾されている可能性のある)型です。

以下の型は総称してスカラ型と呼ばれます(std::is_scalarも参照)

(C++11以降)
  • これらの型のcv修飾版

以下の型は総称して暗黙的なライフタイム型と呼ばれます

以下の型は総称して自明にコピー可能な型と呼ばれます

以下の型は総称して標準レイアウト型と呼ばれます

(C++11以降)

型特性階層図

cpp types v3.svg

注: SVG画像の要素はクリック可能ですが、最初に新しいブラウザタブで図を開く必要があります。

[編集] 非推奨のカテゴリ

以下の型は総称してPOD型と呼ばれます(std::is_podも参照)

  • スカラ型
  • PODクラス
  • そのような型の配列
  • これらの型のcv修飾版
(C++20で非推奨)

以下の型は総称して自明な型と呼ばれます(std::is_trivialも参照)

(C++11以降)
(C++26で非推奨)

[編集] プログラム定義型

プログラム定義の特殊化とは、C++の標準ライブラリの一部ではなく、実装によって定義されていない明示的特殊化または部分特殊化のことです。

プログラム定義型は以下の型のいずれかです。

  • 実装提供ではないラムダ式のクロージャ型。
(C++11以降)

[編集] 型の命名

名前は、以下の方法で型を参照するように宣言できます。

名前を持たない型は、C++プログラムで参照する必要があることがよくあります。その構文はtype-idとして知られています。型Tを命名するtype-idの構文は、T型の変数または関数の宣言の構文と全く同じですが、識別子を省略し、宣言文法のdecl-specifier-seqtype-specifier-seqに制限され、新しい型はtype-idが非テンプレート型エイリアス宣言の右辺に現れる場合にのみ定義できる点が異なります。

int* p;               // declaration of a pointer to int
static_cast<int*>(p); // type-id is "int*"
 
int a[3];   // declaration of an array of 3 int
new int[3]; // type-id is "int[3]" (called new-type-id)
 
int (*(*x[2])())[3];      // declaration of an array of 2 pointers to functions
                          // returning pointer to array of 3 int
new (int (*(*[2])())[3]); // type-id is "int (*(*[2])())[3]"
 
void f(int);                    // declaration of a function taking int and returning void
std::function<void(int)> x = f; // type template parameter is a type-id "void(int)"
std::function<auto(int) -> void> y = f; // same
 
std::vector<int> v;       // declaration of a vector of int
sizeof(std::vector<int>); // type-id is "std::vector<int>"
 
struct { int x; } b;         // creates a new type and declares an object b of that type
sizeof(struct { int x; });   // error: cannot define new types in a sizeof expression
using t = struct { int x; }; // creates a new type and declares t as an alias of that type
 
sizeof(static int); // error: storage class specifiers not part of type-specifier-seq
std::function<inline void(int)> f; // error: neither are function specifiers

宣言文法の名前が削除されたdeclarator部分はabstract-declaratorと呼ばれます。

Type-idは以下の状況で使用できます。

(C++17まで)

Type-idは以下の状況でいくつかの修正を加えて使用できます。

  • 関数のパラメータリスト内(パラメータ名が省略されている場合)、type-idはtype-specifier-seqの代わりにdecl-specifier-seqを使用します(特に、一部の記憶域クラス指定子が許可されます);
  • ユーザー定義変換関数の名前内で、抽象宣言子には関数演算子または配列演算子を含めることはできません。

[編集] 詳細な型指定子

詳細な型指定子は、以前に宣言されたクラス名(class、struct、またはunion)または以前に宣言されたenum名が非型宣言によって隠蔽されていた場合でも、それを参照するために使用できます。また、新しいクラス名を宣言するためにも使用できます。

詳細は詳細な型指定子を参照してください。

[編集] 静的型

プログラムのコンパイル時解析の結果として得られる式の型は、その式の静的型として知られています。静的型はプログラムの実行中に変化しません。

[編集] 動的型

何らかのglvalue式ポリモーフィックオブジェクトを参照している場合、その最も派生したオブジェクトの型は動的型として知られています。

// given
struct B { virtual ~B() {} }; // polymorphic type
struct D : B {};               // polymorphic type
 
D d; // most-derived object
B* ptr = &d;
 
// the static type of (*ptr) is B
// the dynamic type of (*ptr) is D

prvalue式の場合、動的型は常に静的型と同じです。

[編集] 不完全型

以下の型は不完全型です。

  • void(cv修飾されている可能性がある);
  • 不完全に定義されたオブジェクト型:
    • 宣言されているが(例えば前方宣言によって)定義されていないクラス型;
    • 不明な境界の配列;
    • 不完全型の要素の配列;
    • 列挙型の宣言時点からその基底型が決定されるまで。

その他のすべての型は完全です。

以下のいずれかの状況では、型Tが完全であることが求められます。

(一般に、Tのサイズとレイアウトがわかっている必要がある場合。)

これらの状況のいずれかが翻訳単位で発生した場合、型の定義は同じ翻訳単位に現れる必要があります。そうでない場合、必須ではありません。

不完全に定義されたオブジェクト型は完了させることができます。

  • クラス型(例:class X)は、翻訳単位のある時点では不完全と見なされ、後で完全と見なされるかもしれません。class X型は両方の時点で同じ型です。
struct X;            // declaration of X, no definition provided yet
extern X* xp;        // xp is a pointer to an incomplete type:
                     // the definition of X is not reachable
 
void foo()
{
    xp++;            // ill-formed: X is incomplete
}
 
struct X { int i; }; // definition of X
X x;                 // OK: the definition of X is reachable
 
void bar()
{
    xp = &x;         // OK: type is “pointer to X”
    xp++;            // OK: X is complete
}
  • 配列オブジェクトの宣言された型が不完全クラス型の配列であるため不完全である可能性があります。クラス型が翻訳単位で後で完了した場合、配列型は完全になります。これらの2つの時点での配列型は同じ型です。
  • 配列オブジェクトの宣言された型が不明な境界の配列であり、したがって翻訳単位のある時点では不完全であり、後で完全になる可能性があります。これらの2つの時点での配列型(「Tの不明な境界の配列」と「N個のTの配列」)は異なる型です。

不明な境界の配列へのポインタまたは参照の型は、永続的に不完全型を指すか参照します。typedef宣言によって命名された不明な境界の配列は、永続的に不完全型を参照します。どちらの場合も、配列型を完了させることはできません。

extern int arr[];   // the type of arr is incomplete
typedef int UNKA[]; // UNKA is an incomplete type
 
UNKA* arrp;         // arrp is a pointer to an incomplete type
UNKA** arrpp;
 
void foo()
{
    arrp++;         // error: UNKA is an incomplete type
    arrpp++;        // OK: sizeof UNKA* is known
}
 
int arr[10];        // now the type of arr is complete
 
void bar()
{
    arrp = &arr;    // OK: qualification conversion (since C++20)
    arrp++;         // error: UNKA cannot be completed
}

[編集] 欠陥報告

以下の動作変更を伴う欠陥報告が、以前に公開された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 クラスの定義が現れる翻訳単位の外で
クラスが完全と見なされるか不明瞭であった
クラスはその定義が
このケースで
到達可能であれば
完全である C++98 CWG 2643
不明な境界の配列へのポインタの型は
完了できなかった(しかしそれはすでに完全である)
指し示される配列型は
完了できない C++98 LWG 2139 「ユーザー定義型」の意味が不明瞭であった
代わりに「プログラム定義型」を定義し使用する
LWG 3119 C++11 クロージャ型がプログラム定義型であるか不明瞭であった 明確化された

[編集] 参照

  • C++23標準 (ISO/IEC 14882:2024)
  • 6.8.2 基本型 [basic.fundamental]
  • C++20 standard (ISO/IEC 14882:2020)
  • 6.8.2 基本型 [basic.fundamental]
  • C++17 standard (ISO/IEC 14882:2017)
  • 6.9.1 基本型 [basic.fundamental]
  • C++14 standard (ISO/IEC 14882:2014)
  • 3.9.1 基本型 [basic.fundamental]
  • C++11 standard (ISO/IEC 14882:2011)
  • 3.9.1 基本型 [basic.fundamental]
  • C++98 標準 (ISO/IEC 14882:1998)
  • 3.9.1 基本型 [basic.fundamental]

[編集] 関連項目

型特性 型のプロパティを照会するためのコンパイル時テンプレートベースインターフェース
C ドキュメントについて)

[編集] 外部リンク

1.  Howard HinnantのC++0x型ツリー
English 日本語 中文(简体) 中文(繁體)