Спецификатор типа decltype

Описатель типа decltype предоставляет тип заданного выражения. Описатель типа decltype вместе с ключевое слово " auto ", используется главным образом для разработчиков, которые создают библиотеки шаблонов. Используйте auto и decltype для объявления функции шаблонов, возвращаемый тип которой зависит от типов аргументов его шаблонов. Либо используйте auto и decltype для объявления функции шаблона, которая создает программу-оболочку для вызова другой функции, а затем возвращает возвращаемый тип функции с программой-оболочкой.

 decltype( expression )

Параметры

Параметр

Описание

expression

Выражения. Дополнительные сведения см. в разделе Выражения (C++).

Возвращаемое значение

Тип параметра expression.

Заметки

Описатель типа decltype поддерживается в Visual C++ 2010 или более поздних версиях и может использоваться с машинным или управляемым кодом.

Компилятор использует следующие правила для определения типа параметра expression.

  • Если параметр expression является идентификатором или контролирует доступ к элементу класса, decltype(expression) — это тип сущности с именем expression. Если такая сущность отсутствует или параметр expression именует набор перегруженных функций, компилятор создает сообщение об ошибке.

  • Если параметр expression является вызовом функции или перегруженной функцией оператора, decltype(expression) — это возвращаемый тип функции. Скобки вокруг перегруженного оператора игнорируются.

  • Если параметр expression — rvalue, decltype(expression) — это тип expression. Если параметр expression — это значение lvalue, decltype(expression) — это ссылка значения lvalue на тип expression.

В следующем примере кода продемонстрированы некоторые варианты использования описателя типов decltype. Допустим, во-первых, что были закодированы следующие операторы.

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

Затем изучите типы, возвращаемые четырьмя операторами decltype, в таблице ниже.

Оператор

Тип

Примечания

decltype(fx());

const int&&

Ссылка rvalue на const int.

decltype(var);

int

Тип переменной var.

decltype(a->x);

double

Тип членского доступа.

decltype((a->x));

const double&

Внутренние скобки вызывают оценку оператора в качестве выражения, а не членского доступа. А поскольку a объявляется как указатель const, тип является ссылкой на const double.

Decltype и Auto

Используйте описатель типа decltype вместе с ключевым словом auto, чтобы объявить функцию шаблона, возвращаемый тип которой зависит от типов аргументов шаблонов. Например, рассмотрим следующий пример кода, в котором возвращаемый тип функции шаблона зависит от типов аргументов шаблона. В примере кода заполнитель UNKNOWN указывает, что возвращаемый тип не может быть указан.

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

Внедрение описателя типа decltype позволяет разработчику получить тип выражения, возвращаемого функцией шаблона. Используйте альтернативный синтаксис объявления функций (см. ниже), ключевое слово auto и описатель типа decltype для объявления поздно заданный возвращаемого типа. Поздно заданный возвращаемый тип определяется, когда происходит компиляция, а не кодирование объявления.

Следующий прототип иллюстрирует синтаксис альтернативного объявления функции. Обратите внимание, что квалификаторы const и volatile и спецификация исключений throw являются необязательными. Заполнитель function_body представляет составную инструкцию, которая определяет действия функции. В качестве рекомендации по созданию кода учтите следующее: местозаполнитель expression в операторе decltype должен соответствовать выражению, заданному оператором return, если имеется, в function_body.

auto function_name(parametersнеоб) constнеоб volatileнеоб −> decltype(expression) throwнеоб {function_body};

В следующем примере кода поздно заданный возвращаемый тип функции шаблона myFunc определяется типами аргументов шаблона t и u. В соответствии с рекомендацией в данном примере кода также используются ссылки rvalue и шаблон функций forward, поддерживающий точную пересылку. Дополнительные сведения см. в разделе Декларатор ссылки Rvalue: &&.

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); }; 

Decltype и функции пересылки

Функции пересылки создают программы-оболочек для вызовов других функций. Рассмотрим шаблон функции, который пересылает свои аргументы (или результаты выражения с этими аргументами) другой функции. Кроме того, функция пересылки возвращает результат вызова другой функции. В этом сценарии возвращаемый тип функции пересылки должен совпадать с возвращаемым типом функции в программе-оболочке.

В этом сценарии невозможно создать подобающее выражение типа без описателя типа decltype. Описатель типа decltype включает универсальные функции пересылки, поскольку не теряет необходимой информации о том, возвращает ли функция ссылочный тип. Пример кода функции пересылки см. в предыдущем примере шаблонной функции myFunc.

Пример

В следующем примере кода объявляется поздно заданный возвращаемый тип шаблонной функции Plus(). Функция Plus обрабатывает два свои операнда с перегрузкой operator+. Следовательно, интерпретация добавочного оператора (+) и возвращаемый тип функции Plus зависят от типов аргументов функции.

// decltype_1.cpp
// compile with: /EHsc
//
#include "stdafx.h"
#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);
   }

public:
   X(int data) : m_data(data) {}
   int Dump() const { return m_data;}
private:
   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;
}

Вывод

Данный пример кода дает следующие результаты.

13

13.5

Здравствуй, мир!

42

Требования

Visual C++ 2010 и выше.

См. также

Ссылки

Простые имена типов