Namespaces
Variants

decltype specifier (since C++11)

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
const / volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

エンティティの宣言された型、または式の型と値カテゴリを検査します。

目次

構文

decltype ( エンティティ ) (1)
decltype ( ) (2)

説明

1) 引数が括弧で囲まれていない id-expression または括弧で囲まれていない class member access 式の場合、decltypeはこの式によって命名される entity の型を生成する。そのようなentityが存在しない場合、または引数がオーバーロードされた関数のセットを命名する場合、プログラムは不適格となる。

引数が structured binding を命名する括弧で囲まれていない id-expression の場合、decltypeは referenced type (構造化バインディング宣言の仕様で記述されている)を生成する。

(C++17以降)

引数が constant template parameter を命名する括弧で囲まれていない id-expression の場合、decltypeはテンプレートパラメータの型を生成する(テンプレートパラメータがプレースホルダ型で宣言されている場合、必要な型推論を実行した後)。entityがテンプレートパラメータオブジェクト(constオブジェクト)であっても、型は非constとなる。

(C++20以降)
2) 引数が型 T のその他の式である場合、かつ
a) expression value category xvalue の場合、decltypeは T && を返す;
b) expression の値カテゴリが lvalue の場合、decltypeは T & を返す;
c) expression の値カテゴリが prvalue の場合、decltypeは T を返す。

expression がクラス型のprvalueを返す関数呼び出し、または右辺オペランドがそのような関数呼び出しである コンマ式 の場合、そのprvalueに対して一時オブジェクトは導入されない。

(C++17まで)

expression が(丸括弧で囲まれた可能性のある) 即時呼び出し 以外のprvalueである場合、そのprvalueから一時オブジェクトは 実体化 されない:そのようなprvalueは結果オブジェクトを持たない。

(C++17以降)
一時オブジェクトが作成されないため、その型は 完全 である必要がなく、 デストラクタ が利用可能である必要もなく、 抽象 クラスでも構わない。この規則は部分式には適用されない: decltype ( f ( g ( ) ) ) において、 g ( ) は完全型でなければならないが、 f ( ) は完全型である必要はない。

オブジェクトの名前が括弧で囲まれている場合、通常の左辺値式として扱われることに注意してください。したがって、 decltype ( x ) decltype ( ( x ) ) はしばしば異なる型になります。

decltype は、ラムダ関連の型やテンプレートパラメータに依存する型など、標準的な記法では宣言が困難または不可能な型を宣言する際に有用です。

注記

機能テストマクロ 規格 機能
__cpp_decltype 200707L (C++11) decltype

キーワード

decltype

#include <cassert>
#include <iostream>
#include <type_traits>
struct A { double x; };
const A* a;
decltype(a->x) y;       // yの型はdouble(宣言された型)
decltype((a->x)) z = y; // zの型はconst double&(左辺値式)
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) // 戻り値の型はテンプレートパラメータに依存
                                      // 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*)>,
    "単にautoを返すだけでは完全転送にはならない");
decltype(auto) getRefFwdGood(const int* p) { return getRef(p); }
static_assert(std::is_same_v<decltype(getRefFwdGood), const int&(const int*)>,
    "decltype(auto)を返すことで戻り値の型を完全転送する");
// 代替案:
auto getRefFwdGood1(const int* p) -> decltype(getRef(p)) { return getRef(p); }
static_assert(std::is_same_v<decltype(getRefFwdGood1), const int&(const int*)>,
    "decltype(戻り値式)を返すことでも戻り値の型を完全転送する");
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)>,
        "ラムダ関数の型は一意で名前を持たない");
    decltype(f) g = f;
    std::cout << f(3, 3) << ' ' << g(3, 3) << '\n';
}

出力:

42 42

参考文献

拡張コンテンツ
  • C++23規格 (ISO/IEC 14882:2024):
  • 9.2.9.5 Decltype指定子 [dcl.type.decltype]
  • C++20規格 (ISO/IEC 14882:2020):
  • 9.2.8.4 Decltype指定子 [dcl.type.decltype]
  • C++17規格 (ISO/IEC 14882:2017):
  • TBD Decltype指定子 [dcl.type.decltype]
  • C++14規格 (ISO/IEC 14882:2014):
  • TBD Decltype指定子 [dcl.type.decltype]
  • C++11規格 (ISO/IEC 14882:2011):
  • TBD Decltype指定子 [dcl.type.decltype]

関連項目

auto 指定子 (C++11) 式から推論される型を指定する
(C++11)
未評価コンテキストで使用するためのテンプレート型引数のオブジェクトへの参照を取得する
(関数テンプレート)
(C++11)
2つの型が同じかどうかをチェックする
(クラステンプレート)