decltype (C++)decltype (C++)

decltype型指定子は、指定された式の型を生成します。The decltype type specifier yields the type of a specified expression. decltypeと共に指定子を入力、 auto キーワードテンプレートのライブラリを作成する開発者を主に役に立ちます。The decltype type specifier, together with the auto keyword, is useful primarily to developers who write template libraries. 使用autodecltypeテンプレート関数の戻り値を宣言する型は、テンプレート引数の型に依存します。Use auto and decltype to declare a template function whose return type depends on the types of its template arguments. または、使用してautodecltypeを別の関数の呼び出しをラップし、ラップされた関数の戻り値の型を返すテンプレート関数を宣言します。Or, use auto and decltype to declare a template function that wraps a call to another function, and then returns the return type of the wrapped function.


decltype( expression )


パラメーターParameter 説明Description
式 (expression)expression 任意の式を指定します。An expression. 詳細については、次を参照してください。します。For more information, see Expressions.

戻り値Return Value

種類、パラメーター。The type of the expression parameter.


Decltype型指定子は、Visual Studio 2010 またはそれ以降のバージョンでサポートされて、ネイティブまたはマネージ コードで使用できます。The decltype type specifier is supported in Visual Studio 2010 or later versions, and can be used with native or managed code. decltype(auto) (C++14) は Visual Studio 2015 以降でサポートされています。decltype(auto) (C++14) is supported in Visual Studio 2015 and later.

コンパイラの種類を決定する、次の規則を使用して、パラメーター。The compiler uses the following rules to determine the type of the expression parameter.

  • 場合、パラメーターは、識別子またはクラス メンバーに対するアクセスdecltype(expression)によってという名前のエンティティの型であるします。If the expression parameter is an identifier or a class member access, decltype(expression) is the type of the entity named by expression. このようなエンティティが存在しない場合、またはパラメーター名のオーバー ロードされた関数のセットをコンパイラがエラー メッセージが生成されます。If there is no such entity or the expression parameter names a set of overloaded functions, the compiler yields an error message.

  • 場合、パラメーターが関数またはオーバー ロードされた演算子関数では、呼び出しdecltype(expression)は関数の戻り値の型。If the expression parameter is a call to a function or an overloaded operator function, decltype(expression) is the return type of the function. オーバーロードされた演算子を囲んでいるかっこは無視されます。Parentheses around an overloaded operator are ignored.

  • 場合、パラメーターは、右辺値decltype(expression)の型であるします。If the expression parameter is an rvalue, decltype(expression) is the type of expression. 場合、パラメーターは、左辺値decltype(expression)は、左辺値参照の型にします。If the expression parameter is an lvalue, decltype(expression) is an lvalue reference to the type of expression.

次のコード例に示しますのいくつかの使用、 decltype指定子を入力します。The following code example demonstrates some uses of the decltype type specifier. 最初に次のステートメントを記述したとします。First, assume that you have coded the following statements.

int var;
const int&& fx();
struct A { double x; }
const A* a = new A();

次に、4 つによって返される型を調べるdecltype次の表のステートメント。Next, examine the types that are returned by the four decltype statements in the following table.

ステートメントStatement Type メモNotes
decltype(fx()); const int&& 右辺値参照const intします。An rvalue reference to a const int.
decltype(var); intint 変数 var の型。The type of variable var.
decltype(a->x); doubledouble メンバー アクセスの型。The type of the member access.
decltype((a->x)); const double& 内側のかっこは、ステートメントをメンバー アクセスではなく式として評価します。The inner parentheses cause the statement to be evaluated as an expression instead of a member access. aとして宣言されている、constポインター型はへの参照をconst 倍します。And because a is declared as a const pointer, the type is a reference to const double.

decltype および autoDecltype and Auto

C++ 14 で使用できますdecltype(auto)いない後続の戻り値の型テンプレート関数の戻り値の型を宣言すると、テンプレート引数の型に依存します。In C++14, you can use decltype(auto) with no trailing return type to declare a template function whose return type depends on the types of its template arguments.

C++ 11 で使用することができます、 decltypeと同時に後続の戻り値の型指定子を入力、autoキーワード、テンプレート関数の戻り値の型を宣言するは、そのテンプレートの種類によって異なります。引数。In C++11, you can use the decltype type specifier on a trailing return type, together with the auto keyword, to declare a template function whose return type depends on the types of its template arguments. たとえば、テンプレート関数の戻り値の型がテンプレート引数の型に依存している次のコード例について考えます。For example, consider the following code example in which the return type of the template function depends on the types of the template arguments. コードの例で、不明なプレース ホルダーでは、戻り値の型を指定できないことを示します。In the code example, the UNKNOWN placeholder indicates that the return type cannot be specified.

template<typename T, typename U>
UNKNOWN func(T&& t, U&& u){ return t + u; };

導入に伴い、 decltype型指定子により、開発者は、テンプレート関数によって返される式の型を取得します。The introduction of the decltype type specifier enables a developer to obtain the type of the expression that the template function returns. 使用して、代替関数宣言の構文後で、表示される、autoキーワード、およびdecltype宣言指定子を入力、 指定された遅延型を返します。Use the alternative function declaration syntax that is shown later, the auto keyword, and the decltype type specifier to declare a late-specified return type. 遅延指定された戻り値の型は、宣言がコード化されたときではなく、コンパイルされたときに決定します。The late-specified return type is determined when the declaration is compiled, instead of when it is coded.

次のプロトタイプは代替関数宣言の構文について説明します。The following prototype illustrates the syntax of an alternative function declaration. なお、 constvolatile修飾子、およびthrow 例外の指定は省略可能です。Note that the const and volatile qualifiers, and the throw exception specification are optional. Function_bodyプレース ホルダーは、関数の動作を指定する複合ステートメントを表します。The function_body placeholder represents a compound statement that specifies what the function does. コーディングのプラクティスとして、内のプレース ホルダー、 decltypeステートメントがで指定された式に一致する必要があります、return文では、に存在する場合、function_bodyします。As a best coding practice, the expression placeholder in the decltype statement should match the expression specified by the return statement, if any, in the function_body.

auto function_name ( パラメーターopt ) constopt volatileopt -> decltype ( ) throwopt { function_body };auto function_name ( parametersopt ) constopt volatileopt -> decltype( expression ) throwopt { function_body };

次のコード例では、myFunc テンプレート関数の遅延指定された戻り値の型は、テンプレート引数 tu の型によって決まります。In the following code example, the late-specified return type of the myFunc template function is determined by the types of the t and u template arguments. コーディングのプラクティスとして、このコード例もで右辺値参照とforward関数テンプレートは、サポート完全転送します。As a best coding practice, the code example also uses rvalue references and the forward function template, which support perfect forwarding. 詳細については、「右辺値参照宣言子: &&」を参照してください。For more information, see Rvalue Reference Declarator: &&.

template<typename T, typename U>
auto myFunc(T&& t, U&& u) -> decltype (forward<T>(t) + forward<U>(u))
        { return forward<T>(t) + forward<U>(u); };

template<typename T, typename U>
decltype(auto) myFunc(T&& t, U&& u)
        { return forward<T>(t) + forward<U>(u); };

Decltype および転送関数 (C++11)Decltype and Forwarding Functions (C++11)

転送関数は、他の関数の呼び出しをラップします。Forwarding functions wrap calls to other functions. 関数テンプレートで、引数、またはそれらの引数を含む式の結果を別の関数に転送する場合を考えます。Consider a function template that forwards its arguments, or the results of an expression that involves those arguments, to another function. さらに、転送関数は、他の関数を呼び出した結果を返します。Furthermore, the forwarding function returns the result of calling the other function. このシナリオでは、転送関数の戻り値の型は、ラップされた関数の戻り値の型と同じである必要があります。In this scenario, the return type of the forwarding function should be the same as the return type of the wrapped function.

このシナリオではなく適切な型式を記述することはできません、 decltype指定子を入力します。In this scenario, you cannot write an appropriate type expression without the decltype type specifier. Decltype型指定子は、関数が参照型を返すかどうかに関する必要な情報が失われないため、ジェネリック転送関数を使用します。The decltype type specifier enables generic forwarding functions because it does not lose required information about whether a function returns a reference type. 転送関数のコード例については、前の myFunc テンプレート関数の例を参照してください。For a code example of a forwarding function, see the previous myFunc template function example.


次のコード例は、テンプレート関数 Plus() の遅延指定の戻り値の型を宣言します。The following code example declares the late-specified return type of template function Plus(). Plus関数と 2 つのオペランドを処理する、 operator + オーバー ロードします。The Plus function processes its two operands with the operator+ overload. その結果、プラス演算子 (+) と Plus 関数の戻り値の型の解釈は、関数の引数の型によって異なります。Consequently, the interpretation of the plus operator (+) and the return type of the Plus function depends on the types of the function arguments.

// decltype_1.cpp
// compile with: cl /EHsc decltype_1.cpp

#include <iostream>
#include <string>
#include <utility>
#include <iomanip>

using namespace std;

template<typename T1, typename T2>
auto Plus(T1&& t1, T2&& t2) ->
   decltype(forward<T1>(t1) + forward<T2>(t2))
   return forward<T1>(t1) + forward<T2>(t2);

class X
   friend X operator+(const X& x1, const X& x2)
      return X(x1.m_data + x2.m_data);

   X(int data) : m_data(data) {}
   int Dump() const { return m_data;}
   int m_data;

int main()
   // Integer
   int i = 4;
   cout <<
      "Plus(i, 9) = " <<
      Plus(i, 9) << endl;

   // Floating point
   float dx = 4.0;
   float dy = 9.5;
   cout <<
      setprecision(3) <<
      "Plus(dx, dy) = " <<
      Plus(dx, dy) << endl;

   // String
   string hello = "Hello, ";
   string world = "world!";
   cout << Plus(hello, world) << endl;

   // Custom type
   X x1(20);
   X x2(22);
   X x3 = Plus(x1, x2);
   cout <<
      "x3.Dump() = " <<
      x3.Dump() << endl;
Plus(i, 9) = 13
Plus(dx, dy) = 13.5
Hello, world!
x3.Dump() = 42


Visual Studio 2017 以降: コンパイラは、テンプレートは宣言ではなくインスタンス化されるときに、decltype 引数を解析します。Visual Studio 2017 and later: The compiler parses decltype arguments when the templates are declared rather than instantiated. その結果、decltype 引数に非依存の特殊化が見つかった場合、インスタンス化時まで遅延されずにすぐに処理され、結果として発生したエラーは、その時点で診断されます。Consequently, if a non-dependent specialization is found in the decltype argument, it will not be deferred to instantiation-time and will be processed immediately and any resulting errors will be diagnosed at that time.

次の例は、宣言時に発生するこのようなコンパイラ エラーを示しています。The following example shows such a compiler error that is raised at the point of declaration:

#include <utility>
template <class T, class ReturnT, class... ArgsT> class IsCallable
   struct BadType {};
   template <class U>
   static decltype(std::declval<T>()(std::declval<ArgsT>()...)) Test(int); //C2064. Should be declval<U>
   template <class U>
   static BadType Test(...);
   static constexpr bool value = std::is_convertible<decltype(Test<T>(0)), ReturnT>::value;

constexpr bool test1 = IsCallable<int(), int>::value;
static_assert(test1, "PASS1");
constexpr bool test2 = !IsCallable<int*, int>::value;
static_assert(test2, "PASS2");


Visual Studio 2010 またはそれ以降のバージョン。Visual Studio 2010 or later versions.

decltype(auto) Visual Studio 2015 またはそれ以降が必要です。decltype(auto) requires Visual Studio 2015 or later.