decltype 指定子 (C++11 以降)
From cppreference.com
エンティティの宣言された型、または式の型と値カテゴリを検査します。
目次 |
[編集] 構文
decltype ( entity ) |
(1) | ||||||||
decltype ( expression ) |
(2) | ||||||||
[編集] 説明
1) 引数が括弧で囲まれていない id-expression または括弧で囲まれていない クラスメンバーアクセス 式の場合、decltype はこの式によって指定される entity の型を返します。そのようなエンティティがない場合、または引数がオーバーロードされた関数の集合を指定する場合、プログラムは不正な形式です。
|
引数が 構造化束縛 を指定する括弧で囲まれていない id-expression の場合、decltype は *参照型* (構造化束縛宣言の仕様で説明) を返します。 |
(C++17以降) |
|
引数が 非型テンプレートパラメータ を指定する括弧で囲まれていない id-expression の場合、decltype はテンプレートパラメータの型を返します (テンプレートパラメータがプレースホルダー型で宣言されている場合、必要な型推論を実行した後)。エンティティがテンプレートパラメータオブジェクト (const オブジェクト) であっても、型は非 const です。 |
(C++20以降) |
2) 引数が型
T のその他の式であり、かつc) expression の値カテゴリが prvalue の場合、decltype は T を返します。
一時オブジェクトが作成されないため、型は 完全 である必要はなく、利用可能な デストラクタ を持つ必要もなく、抽象 であっても構いません。このルールは副式には適用されません。decltype(f(g())) では、g() は完全な型を持つ必要がありますが、f() はそうである必要はありません。
|
expression がクラス型の prvalue を返す関数呼び出し、または右オペランドがそのような関数呼び出しである コンマ式 である場合、その prvalue に対して一時オブジェクトは導入されません。 |
(C++17まで) |
|
expression が (括弧で囲まれている可能性のある) 即時呼び出し 以外の prvalue (C++20 以降) の場合、その prvalue から一時オブジェクトは 具現化 されません。そのような prvalue には結果オブジェクトがありません。 |
(C++17以降) |
オブジェクトの名前が括弧で囲まれている場合、それは通常の左辺値式として扱われるため、decltype(x) と decltype((x)) はしばしば異なる型になります。
decltype は、ラムダ関連の型やテンプレートパラメータに依存する型のように、標準表記では宣言が困難または不可能な型を宣言するのに役立ちます。
[編集] 備考
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_decltype |
200707L |
(C++11) | decltype |
[編集] キーワード
[編集] 例
このコードを実行
#include <cassert> #include <iostream> #include <type_traits> struct A { double x; }; const A* a; decltype(a->x) y; // type of y is double (declared type) decltype((a->x)) z = y; // type of z is const double& (lvalue expression) template<typename T, typename U> auto add(T t, U u) -> decltype(t + u) // return type depends on template parameters // return type can be deduced since C++14 { return t + u; } const int& getRef(const int* p) { return *p; } static_assert(std::is_same_v<decltype(getRef), const int&(const int*)>); auto getRefFwdBad(const int* p) { return getRef(p); } static_assert(std::is_same_v<decltype(getRefFwdBad), int(const int*)>, "Just returning auto isn't perfect forwarding."); decltype(auto) getRefFwdGood(const int* p) { return getRef(p); } static_assert(std::is_same_v<decltype(getRefFwdGood), const int&(const int*)>, "Returning decltype(auto) perfectly forwards the return type."); // Alternatively: auto getRefFwdGood1(const int* p) -> decltype(getRef(p)) { return getRef(p); } static_assert(std::is_same_v<decltype(getRefFwdGood1), const int&(const int*)>, "Returning decltype(return expression) also perfectly forwards the return type."); int main() { int i = 33; decltype(i) j = i * 2; static_assert(std::is_same_v<decltype(i), decltype(j)>); assert(i == 33 && 66 == j); auto f = [i](int av, int bv) -> int { return av * bv + i; }; auto h = [i](int av, int bv) -> int { return av * bv + i; }; static_assert(!std::is_same_v<decltype(f), decltype(h)>, "The type of a lambda function is unique and unnamed"); decltype(f) g = f; std::cout << f(3, 3) << ' ' << g(3, 3) << '\n'; }
出力
42 42
[編集] 参照
| 拡張コンテンツ |
|---|
|
| このセクションは未完成です 理由: 修正が必要。参照: Talk: Wrong References。 |
[編集] 関連項目
auto 指定子 (C++11) |
式から推論される型を指定します |
| (C++11) |
評価されない文脈で使用するために、テンプレート型引数のオブジェクトへの参照を取得する (関数テンプレート) |
| (C++11) |
2つの型が同じであるかをチェックする (クラステンプレート) |
| C ドキュメント ( typeof について)
| |