Перейти к содержимому

Decltype c что это

  • автор:

что возвращает decltype и как он работает?

Всем здравствуйте. Я начал недавно изучать c++ и столкнулся с оператором decltype. Насколько я знаю, операторы как и функции возвращают определенное значение, но ознакомившись с документацией на сайте microsoft (https://docs.microsoft.com/ru-ru/cpp/cpp/decltype-cpp?view=msvc-160) я увидел следующую строчку «decltype Описатель типа возвращает тип указанного выражения.». Насколько мне известно тип, в качестве возвращаемого значения, не может быть возвращен, но тогда как это происходит? Заранее спасибо, надеюсь вы поможете.

Отслеживать
задан 26 ноя 2020 в 19:16
n 1 k z z z n 1 k z z z
1,491 4 4 серебряных знака 21 21 бронзовый знак
decltype — спецификатор, а не оператор.
26 ноя 2020 в 19:26
В можно про это по подробнее?
26 ноя 2020 в 19:28

2 ответа 2

Сортировка: Сброс на вариант по умолчанию

int a; . 

Хочу объявить переменную того же типа, что и a .

decltype(a) b; 

Грубо — но для понимания сойдет — decltype(a) заменяется типом, с которым была объявлена a — declared type

Отслеживать
ответ дан 26 ноя 2020 в 19:32
219k 15 15 золотых знаков 119 119 серебряных знаков 230 230 бронзовых знаков

Спасибо за ответ, извините за настойчивость, но мне хотелось бы кое-что уточнить, а конкретно меня смущает данная фраза «decltype Описатель типа возвращает тип указанного выражения.» Каким образом можно возвращать тип? Или это просто некая условность?

26 ноя 2020 в 19:46

@n1kzzz, если посмотреть англ. версию документации по приведённой в вашем вопросе ссылке, то там будет такая фраза: «The decltype type specifier yields the type of a specified expression». Это скорее не «возвращает», а что-то вроде «даёт/производит/вырабатывает». В общем, корявый перевод 🙂

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

Иногда необходимо определить переменную, тип которой компилятор выводит из выражения, но не использовать это выражение для инициализации переменной. Для таких случаев новый стандарт вводит спецификатор типа decltype, возвращающий тип его операнда. Компилятор анализирует выражение и определяет его тип, но не вычисляет его результат.

decltype(f()) sum = x; // sum имеет тот тип,

// который возвращает функция f

Здесь компилятор не вызывает функцию f(), но он использует тип, который возвратил бы такой вызов для переменной sum. Таким образом, компилятор назначает переменной sum тот же тип, который был бы возвращен при вызове функции f().

Таким образом, спецификатор decltype учитывает спецификатор const верхнего уровня и ссылки, но несколько отличается от того, как работает спецификатор auto. Когда выражение, к которому применен спецификатор decltype, является переменной, он возвращает тип этой переменной, включая спецификатор const верхнего уровня и ссылки.

const int ci = 0, &cj = ci;

decltype(ci) x = 0; // x имеет тип const int

decltype(cj) y = x; // y имеет тип const int& и связана с x

decltype(сj) z; // ошибка: z — ссылка, она должна быть инициализирована

Поскольку cj — ссылка, decltype (cj) — ссылочный тип. Как и любую другую ссылку, ссылку z следует инициализировать.

Следует заметить, что спецификатор decltype — единственный контекст, в котором переменная определена, поскольку ссылка не рассматривается как синоним объекта, на который она ссылается.

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

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

// decltype выражение может быть ссылочным типом

decltype(r + 0) b; // ok: сложение возвращает тип int; b имеет тип int

decltype(*p) с; // ошибка: с имеет тип int& и требует инициализации

Здесь r — ссылка, поэтому decltype(r) возвращает ссылочный тип. Если необходим тип, на который ссылается ссылка r, можно использовать ее в таком выражении, как r + 0, поскольку оно возвращает значение не ссылочного типа.

С другой стороны, оператор обращения к значению — пример выражения, для которого спецификатор decltype возвращает ссылку. Как уже упоминалось, при обращении к значению указателя возвращается объект, на который он указывает. Кроме того, этому объекту можно присвоить значение. Таким образом, decltype(*p) выведет тип int&, а не просто int.

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

// decltype переменной в скобках — всегда ссылка

decltype((i)) d; // ошибка: d — int& и должна инициализироваться

decltype(i) e; // ok: e имеет тип int (не инициализирована)

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

Упражнения раздела 2.5.3

Упражнение 2.36. Определите в следующем коде тип каждой переменной и значения, которые будет иметь каждая из них по завершении.

Упражнение 2.37. Присвоение — это пример выражения, которое возвращает ссылочный тип. Тип — это ссылка на тип левого операнда. Таким образом, если переменная i имеет тип int, то выражение i = x имеет тип int&. С учетом этого определите тип и значение каждой переменной в следующем коде:

decltype(а = b) d = а;

Упражнение 2.38. Опишите различия выведения типа спецификаторами decltype и auto. Приведите пример выражения, где спецификаторы auto и decltype выведут тот же тип, и пример, где они выведут разные типы.

decltype

decltype — ключевое слово языка программирования C++, которое появилось в обновлённом стандарте C++11. Наряду с ключевым словом auto оно используется для выведения типов выражений, получаемых в качестве своего аргумента.

Ключевое слово decltype нашло широкое распространение при работе с обобщёнными типами данных. Различие между decltype и auto сводится к типу возвращаемого значения: результат использования auto теряет квалификаторы типов const и & , а результат использования decltype сохраняет их для дальнейшей работы [1] [2] .

Также в стандарте C++11 ключевое слово decltype можно использовать для объявления типа возвращаемого функцией значения в тех случаях, когда применяется новый способ записи сигнатуры функции (в котором возвращаемое значение следует за списком её параметров) [3] .

В обновлённом стандарте языка C++14 появилась возможность объявлять переменные со спецификатором типа decltype(auto) , который предписывает компилятору выбирать для них тип данных на основе типа инициализатора [4] .

Примечания [ править | править код ]

  1. ↑Gregoire, 2018, The decltype Keyword, p. 40.
  2. ↑Gregoire, 2018, Return Type of Function Templates, p. 405.
  3. ↑Olsson, 2018, Auto and Decltype, p. 60.
  4. ↑Wayback Machine en.cppreference.com

Источники [ править | править код ]

  • Marc Gregoire. Professional C++ : [ англ. ] . — Fourth Edition. — John Wiley & Sons, 2018. — ISBN 978-1-119-42130-6.
  • Mikael Olsson. C++17 Quick Syntax Reference : A Pocket Guide to the Language, APIs and Library : [ англ. ] . — Third Edition. — Apress, 2018. — ISBN 978-1-4842-3599-7. — doi:Источник — https://ru.ruwiki.ru/w/index.php?title=Decltype&oldid=126512093
  • Синтаксис C++
  • Нововведения стандарта C++11

decltype (C++)

Описатель 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 . 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

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

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

template UNKNOWN func(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 opt opt volatile -> decltype( expression ) noexcept function_body >;

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

//C++11 template auto myFunc(T&& t, U&& u) -> decltype (forward(t) + forward(u)) < return forward(t) + forward(u); >; //C++14 template decltype(auto) myFunc(T&& t, U&& u) < return forward(t) + forward(u); >; 

decltype функции пересылки (C++11)

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

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

Примеры

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

// decltype_1.cpp // compile with: cl /EHsc decltype_1.cpp #include #include #include #include using namespace std; template auto Plus(T1&& t1, T2&& t2) -> decltype(forward(t1) + forward(t2)) < return forward(t1) + forward(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) = 13 Plus(dx, dy) = 13.5 Hello, world! x3.Dump() = 42 

Visual Studio 2017 и более поздних версий: компилятор анализирует decltype аргументы, когда шаблоны объявляются вместо создания экземпляров. Таким образом, если не зависящая специализация найдена в decltype аргументе, она не будет отложена до времени создания экземпляра; она обрабатывается немедленно и все результирующий ошибки диагностируются в то время.

В следующем примере показана такая ошибка компилятора, возникающая во время объявления.

#include template class IsCallable < public: struct BadType <>; template static decltype(std::declval()(std::declval(). )) Test(int); //C2064. Should be declval template static BadType Test(. ); static constexpr bool value = std::is_convertible::value; >; constexpr bool test1 = IsCallable::value; static_assert(test1, "PASS1"); constexpr bool test2 = !IsCallable::value; static_assert(test2, "PASS2"); 

Требования

Visual Studio 2010 или более поздней версии.

decltype(auto) требуется Visual Studio 2015 или более поздней версии.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *