decltype 指定子 - cppreference.com
提供: cppreference.com
エンティティの宣言された型または式の型と値カテゴリを調べます。
構文
decltype ( entity )
|
(1) | (C++11以上) | |||||||
decltype ( expression )
|
(2) | (C++11以上) | |||||||
説明
|
1) 引数が構造化束縛を表す括弧で囲まれていない識別子式の場合、 decltype は参照先の型 (構造化束縛宣言の仕様で説明されます) になります。 |
(C++17以上) |
|
2) 引数が非型テンプレート引数を表す括弧で囲まれていない識別子式の場合、 decltype はそのテンプレート引数の型 (そのテンプレート引数がプレースホルダ型を用いて宣言されている場合はあらゆる必要な型推定を行った後の) になります。 |
(C++20以上) |
3) 引数が括弧で囲まれていない識別子式または括弧で囲まれていないクラスメンバアクセス式の場合、 decltype はその式によって表される entity の型になります。 そのようなエンティティがない場合、または引数がオーバーロード関数の集合を表す場合、プログラムは ill-formed です。
4) 引数がそれ以外の任意の T 型の式の場合、かつ
a) expression の値カテゴリが xvalue の場合、 decltype は T&& になります。
b) expression の値カテゴリが lvalue の場合、 decltype は T& になります。
c) expression の値カテゴリが prvalue の場合、 decltype は T になります。
|
expression がクラス型の prvalue を返す関数呼び出しか、右側の被演算子がそのような関数呼び出しであるコンマ式の場合、一時オブジェクトはその prvalue に対して導入されません。 |
(C++17未満) |
|
expression が即時呼び出し (括弧で囲った場合を含みます) 以外の (C++20以上) prvalue である場合、一時オブジェクトはその prvalue から具体化されません (そのような prvalue は結果オブジェクトを持ちません)。 |
(C++17以上) |
型は完全である必要も利用可能なデストラクタを持つ必要もなく、抽象であっても構いません。 このルールは部分式には適用されません。 例えば decltype(f(g())) の場合、 g() は完全型でなければなりませんが、 f() はその必要はありません。
オブジェクトの名前が括弧で囲まれている場合は普通の lvalue 式として扱われるため、 decltype(x) と decltype((x)) はしばしば異なる型となることに注意してください。
decltype は、ラムダに関連する型やテンプレート引数に依存する型のような、標準の記法を用いて宣言することが難しいまたは不可能な型を宣言するときに便利です。
キーワード
例
#include <iostream> struct A { double x; }; const A* a; decltype(a->x) y; // y の型は double です (宣言された型)。 decltype((a->x)) z = y; // z の型は const double& です (lvalue 式)。 template<typename T, typename U> auto add(T t, U u) -> decltype(t + u) // 戻り値の型はテンプレート引数に依存します。 // C++14 からは戻り値の型を推定することもできます。 { return t+u; } int main() { int i = 33; decltype(i) j = i * 2; std::cout << "i = " << i << ", " << "j = " << j << '\n'; auto f = [](int a, int b) -> int { return a * b; }; decltype(f) g = f; // ラムダ関数の型は一意かつ無名です。 i = f(2, 2); j = g(3, 3); std::cout << "i = " << i << ", " << "j = " << j << '\n'; }
出力:
i = 33, j = 66 i = 4, j = 9