Decltype c что это

Конструкция decltype(auto)

2 ответа 2

auto это «усохший» (decayed) тип выражения, т.е. теряются ссылки и происходит копирование:

auto

В С++11 ключевое слово auto лишено своего первоначального смысла в качестве спецификатора класса хранения и теперь применяется для реализации автоматического выведения типа при условии, что задан явный инициализатор. Компилятор устанавливает тип переменной в тип инициализирующего значения:

можно заменить таким:

decltype

Ключевое слово decltype создает переменную типа, который указан выражением. Приведенный ниже оператор означает «назначить у тот же самый тип, что х», где х представляет собой выражение:

Вот еще пара примеров:

Это особенно полезно в определениях шаблонов, когда тип может быть не определен вплоть до создания специфического экземпляра:

Хвостовой возвращаемый тип

В С++11 появился новый синтаксис для объявления функций, при котором возвращаемый тип указывается после имени функции и списка параметров, а не перед ними:

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

Иллюстрируемая здесь проблема состоит в том, что когда компилятор читает список параметров ef f, Т и U не находятся в области видимости, поэтому любое использование decltype должно находиться после этого списка параметров. Новый синтаксис делает это возможным.

Источник

decltype specifier

Compiler support
Freestanding and hosted
Language
Standard library headers
Named requirements
Feature test macros (C++20)
Language support library
Concepts library (C++20)
Diagnostics library
General utilities library
Strings library
Containers library
Iterators library
Ranges library (C++20)
Algorithms library
Numerics library
Localizations library
Input/output library
Filesystem library (C++17)
Regular expressions library (C++11)
Atomic operations library (C++11)
Thread support library (C++11)
Technical specifications
Symbols index
External libraries
Declarators
reference
pointer
array
Block declarations
simple-declaration
→ structured binding declaration (C++17)
alias declaration (C++11)
namespace alias definition
using-declaration
using-directive
static_assert declaration (C++11)
asm-declaration
opaque enum declaration (C++11)
Other declarations
namespace definition
function declaration
class template declaration
function template declaration
explicit template instantiation (C++11)
explicit template specialization
linkage specification
attribute declaration (C++11)
empty declaration

Inspects the declared type of an entity or the type and value category of an expression.

Contents

[edit] Syntax

[edit] Explanation

1) If the argument is an unparenthesized id-expression or an unparenthesized class member access expression, then decltype yields the type of the entity named by this expression. If there is no such entity, or if the argument names a set of overloaded functions, the program is ill-formed.

If the argument is an unparenthesized id-expression naming a structured binding, then decltype yields the referenced type (described in the specification of the structured binding declaration).

If the argument is an unparenthesized id-expression naming a non-type template parameter, then decltype yields the type of the template parameter (after performing any necessary type deduction if the template parameter is declared with a placeholder type). The type is non-const even if the entity is a template parameter object (which is a const object).

If expression is a function call which returns a prvalue of class type or is a comma expression whose right operand is such a function call, a temporary object is not introduced for that prvalue.

Note that if the name of an object is parenthesized, it is treated as an ordinary lvalue expression, thus decltype ( x ) and decltype ( ( x ) ) are often different types.

decltype is useful when declaring types that are difficult or impossible to declare using standard notation, like lambda-related types or types that depend on template parameters.

Источник

decltype (C++)

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

Синтаксис

decltype( decltype( )

Параметры

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

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

Комментарии

decltype спецификатор типа поддерживается в Visual Studio 2010 или более поздних версиях и может использоваться с машинным или управляемым кодом. decltype(auto) (C++ 14) поддерживается в Visual Studio 2015 и более поздних версиях.

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

Если параметр выражения является идентификатором или доступом к члену класса, то является типом сущности с именем Expression. Если такая сущность или параметр выражения не называет набор перегруженных функций, компилятор выдает сообщение об ошибке.

Если параметр выражения является вызовом функции или перегруженной функции оператора, то аргумент является типом возвращаемого значения функции. Скобки вокруг перегруженного оператора игнорируются.

Если параметр Expression является rvalue, то является типом выражения. Если параметр Expression является левостороннимзначением, то является ссылкой lvalue на тип выражения.

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

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

Decltype и Auto

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

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

auto auto ( ( не следует заменять const const volatile volatile -> decltype( -> opt ) noexcept decltype( < ) >;

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

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

Примеры

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

Требования

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

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

Источник

Секреты auto и decltype

1. Какой тип будет у переменных ri1..riN после выполнения следующего кода?

Скомпилируются ли следующие фрагменты?

Теория

К механизму вывода типов, используемому в шаблонах в С++11 добавилось два новых механизма: auto и decltype. И чтобы жизнь программистам не казалась медом, все эти 3 механизма выводят типы по-своему. Механизм, используемый auto, в точности копирует механизм шаблонов, за исключением типа std::initializer_list.

Объяснений такому поведению немного и все они не отличаются внятностью. Скотт Мейерс, например, по этому поводу пишет так: “I have no idea why type deduction for auto and for templates is not identical. If you know, please tell me!”. В С++14 этот механизм менять не собираются. За объяснение можно попровать принять тот факт, что работают, например, такие удивительные вещи:

Итак, как же `auto` выводит тип? К сожалению, здесь нет простого правила на все случаи жизни, кроме, пожалуй, того, что `auto` при выводе типа в общем случае отбрасывает cv квалификаторы и ссылки. Ниже я перечислю самые важные моменты.

1.
Если тип some_expression T* или const T*, то тип var также будет T* или const T* соответственно. Пока без сюрпизов. Дальше — интереснее. Пожалуй самое важное с практической точки зрения правило заключается в том, что если тип some_expressionT, const T, T& или const T&, то типом var будет T. Это, впрочем, если задуматься, вполне логично, ведь в этом случае значение, возвращаемое some_expression копируется в var и можно смело писать вот так:

2.
В этом случае, ожидаемо, если тип some_expressionT или const T, компилироваться это не будет, так как lvalue ссылку нельзя инициализировать rvalue. Если тип some_expressionT&, то и var будет иметь тип T&. Здесь важным моментом является то, что если тип some_expressionconst T&, то и тип var будет const T&.

3.
Здесь действует придуманное (или по крайней мере озвученное) Скоттом Мейерсом правило “универсальных ссылок”. Оно заключается в том, что тип var будет зависеть от того какая value category у some_expression. Если rvalue, то тип var будет T&&, если же lvalue, то T&. Cv квалификаторы при этом сохраняются.

Auto как параметр функции

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

Однако в с++14 можно будет использовать auto параметры в лямбдах.

decltype

С decltype ситуация с одной стороны сложнее (если посмотреть формальные правила), с другой стороны проще (если выделить основные моменты). Я сформулирую эти правила так, как я их понял.
Итак, следует различать два основных случая применения decltype.
1. decltype(var), когда var — это объявленная переменная (например в функции или как член класса). В этом случае decltype(var) будет иметь в точности тот тип, с которым объявлена переменная.
2. decltype(expr), expr — выражение. В этом случае типом decltype(expr) будет тип, которое могло бы вернуть это выражение, с той оговоркой, что decltype(expr) будет иметь тип T& (const T&), если expr возвращает lvalue, T, если expr возвращает rvalue типа Т (const T) и T&& (const T&&), если expr возвращает xvalue (rvalue reference).

Что значит “могло бы вернуть”? Это значит то, что decltype не вычисляет переданное ему в качестве аргумента выражение.
Несколько поясняющих примеров:

В том случае, если мы не знаем lvalue нам вернет выражение, rvalue или xvalue, а тип использовать хочется, можно воспользоваться стандартным шаблоном std::remove_reference, чтобы “очистить” тип от ссылок.

Decltype(auto)

Это новая “фишка” языка, которая войдет в С++14. Она нужна для сохранения семантики decltype при объявлении auto переменных и будет использоваться в тех случаях, когда нас не будет устраивать то, что auto отбрасывает ссылки и cv квалификаторы и, возможно, в связке с новой возможностью С++14 — выводом типа возвращаемого функцией значения.

В последнем случае мы могли бы написать decltype(foo()), но представьте, если бы вместо foo() было выражение на 2 строчки, а такие в С++ не редкость.

Ответы

Ну и сейчас, загрузив теорию в кэш, можно попытаться ответить на вопросы теста.

Источник

decltype (C++)

The decltype type specifier yields the type of a specified expression. The decltype type specifier, together with the auto keyword, is useful primarily to developers who write template libraries. Use auto and decltype to declare a template function whose return type depends on the types of its template arguments. 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.

Syntax

decltype( expression )

Parameters

expression
An expression. For more information, see Expressions.

Return Value

The type of the expression parameter.

Remarks

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) is supported in Visual Studio 2015 and later.

The compiler uses the following rules to determine the type of the expression parameter.

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.

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.

If the expression parameter is an rvalue, decltype(expression) is the type of expression. If the expression parameter is an lvalue, decltype(expression) is an lvalue reference to the type of expression.

The following code example demonstrates some uses of the decltype type specifier. First, assume that you have coded the following statements.

Next, examine the types that are returned by the four decltype statements in the following table.

Decltype and 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.

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.

The introduction of the decltype type specifier enables a developer to obtain the type of the expression that the template function returns. 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. Note that the const and volatile qualifiers, and the throw exception specification are optional. The function_body placeholder represents a compound statement that specifies what the function does. 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 ( parametersopt ) const opt volatile opt -> decltype( expression ) noexcept opt < function_body >;

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. 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: &&.

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.

In this scenario, you cannot write an appropriate type expression without the decltype type specifier. The decltype type specifier enables generic forwarding functions because it does not lose required information about whether a function returns a reference type. For a code example of a forwarding function, see the previous myFunc template function example.

Examples

Visual Studio 2017 and later: The compiler parses decltype arguments when the templates are declared rather than instantiated. 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:

Requirements

Visual Studio 2010 or later versions.

decltype(auto) requires Visual Studio 2015 or later.

Источник

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

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