Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Описатель decltype типов выдает тип указанного выражения. Описатель decltype типов вместе с auto ключевым словом полезен в первую очередь разработчикам, которые записывают библиотеки шаблонов. Используйте и decltype объявите auto шаблон функции, возвращаемый тип которого зависит от типов его аргументов шаблона. Кроме того, используйте auto и decltype объявите шаблон функции, который упаковывает вызов другой функции, а затем возвращает возвращаемый тип упаковаемой функции.
Синтаксис
decltype(expression)
Параметры
expression
Выражение. Дополнительные сведения см. в разделе Выражения.
Возвращаемое значение
Тип expression параметра.
Замечания
Описатель decltype типов поддерживается в Visual Studio 2010 или более поздних версиях и может использоваться с машинным или управляемым кодом.
decltype(auto) (C++14) поддерживается в Visual Studio 2015 и более поздних версиях.
Компилятор использует следующие правила для определения типа expression параметра.
expressionЕсли параметр является идентификатором или доступом к члену класса,decltype(expression)тип сущности сexpressionименем. Если такой сущности илиexpressionпараметра нет набора перегруженных функций, компилятор выдает сообщение об ошибке.expressionЕсли параметр является вызовом функции или перегруженной функции оператора,decltype(expression)возвращает тип функции. Круглые скобки вокруг перегруженного оператора игнорируются.expressionЕсли параметр является rvalue,decltype(expression)является типомexpression. Если параметр является lvalue,decltype(expression)это ссылка на lvalue типаexpression.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.
В C++14 можно использовать decltype(auto) без конечного типа возврата для объявления шаблона функции, возвращаемый тип которого зависит от типов его аргументов шаблона.
В C++11 можно использовать decltype описатель типов для конечного возвращаемого типа вместе с auto ключевым словом, чтобы объявить шаблон функции, возвращаемый тип которого зависит от типов его аргументов шаблона. Например, рассмотрим следующий пример кода, в котором возвращаемый тип шаблона функции зависит от типов аргументов шаблона. В примере кода заполнитель указывает, UNKNOWN что возвращаемый тип нельзя указать.
template<typename T, typename U>
UNKNOWN func(T&& t, U&& u){ return t + u; }
Введение decltype описателя типов позволяет разработчику получить тип выражения, возвращаемого шаблоном функции. Используйте синтаксис объявления альтернативной функции , показанный позже, auto ключевое слово и decltype описатель типа, чтобы объявить тип возвращаемого значения с поздним значением. Тип возвращаемого значения, заданного в конце, определяется при компиляции объявления, а не при коде.
Следующий прототип иллюстрирует синтаксис альтернативного объявления функции. Квалификаторы const и volatilethrowспецификация исключения являются необязательными . Заполнитель function_body представляет составную инструкцию, которая указывает, что выполняет функция. В качестве оптимальной методики expression написания кода заполнитель в decltype инструкции должен соответствовать выражению, указанному return оператором, если таковой function_bodyимеется.
auto
function_name
(
parameters
выбирать)constвыбиратьvolatileвыбирать->decltype(expression)noexceptвыбирать{function_body};
В следующем примере кода тип возвращаемого myFunc типа шаблона функции определяется типами t аргументов шаблона и u шаблонов. В качестве рекомендации по написанию кода в примере кода также используются ссылки rvalue и forward шаблон функции, поддерживающие идеальную пересылку. Дополнительные сведения см. в справочнике Rvalue: &>.
//C++11
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); }
//C++14
template<typename T, typename U>
decltype(auto) myFunc(T&& t, U&& u)
{ return forward<T>(t) + forward<U>(u); }
decltype функции пересылки (C++11)
Переадресация вызовов функций оболочки для других функций. Рассмотрим шаблон функции, который пересылает свои аргументы или результаты выражения, включающего эти аргументы, в другую функцию. Кроме того, функция пересылки возвращает результат вызова другой функции. В этом сценарии возвращаемый тип функции пересылки должен совпадать с типом возврата упаковаемой функции.
В этом сценарии невозможно написать соответствующее выражение типа без decltype описателя типов. Описатель decltype типов включает универсальные функции пересылки, так как он не теряет необходимые сведения о том, возвращает ли функция ссылочный тип. Пример кода функции пересылки см. в предыдущем myFunc примере шаблона функции.
Примеры
В следующем примере кода объявляется тип возвращаемого значения для шаблона Plus()функции. Функция Plus обрабатывает два операнда с перегрузкой operator+ . Таким образом, интерпретация оператора plus (+) и возвращаемого типа Plus функции зависит от типов аргументов функции.
// 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);
}
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;
}
Plus(i, 9) = 13
Plus(dx, dy) = 13.5
Hello, world!
x3.Dump() = 42
Visual Studio 2017 и более поздних версий: Компилятор анализирует decltype аргументы, когда шаблоны объявляются вместо создания экземпляров. Таким образом, если не зависящая специализация найдена в decltype аргументе, она не будет отложена до времени создания экземпляра; она обрабатывается немедленно и все результирующий ошибки диагностируются в то время.
В следующем примере показана такая ошибка компилятора, которая возникает в момент объявления:
#include <utility>
template <class T, class ReturnT, class... ArgsT> class IsCallable
{
public:
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 или более поздней версии.
decltype(auto) требуется Visual Studio 2015 или более поздней версии.