Спецификатор типа 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 и выше.