Пространства имён
Варианты
Действия

Спецификаторы типа заполнителя (начиная с C++11)

Материал из cppreference.com
< cpp‎ | language
 
 
Язык С++
Общие темы
Управление потоком
Операторы условного выполнения
Операторы итерации (циклы)
Операторы перехода
Функции
Объявление функции
Выражение лямбда-функции
Спецификатор inline
Спецификации динамических исключений(до C++17*)
Спецификатор noexcept(C++11)
Исключения
Пространства имён
Типы
Спецификаторы
decltype(C++11)
auto(C++11)
alignas(C++11)
Спецификаторы длительности хранения
Инициализация
Выражения
Альтернативные представления
Литералы
Логические - Целочисленные - С плавающей запятой
Символьные - Строковые - nullptr(C++11)
Определяемые пользователем(C++11)
Утилиты
Атрибуты(C++11)
Types
Объявление typedef
Объявление псевдонима типа(C++11)
Casts
Неявные преобразования - Явные преобразования
static_cast - dynamic_cast
const_cast - reinterpret_cast
Выделение памяти
Классы
Свойства функции класса
Специальные функции-элементы
Шаблоны
Разное
 
Обьявления
 

Для переменных указывает, что тип объявляемой переменной будет автоматически выведен из её инициализатора.

Для функций указывает, что тип возвращаемого значения будет выведен из их операторов return.

(начиная с C++14)

Для параметров шаблона, не относящихся к типу, указывает, что тип будет выведен из аргумента.

(начиная с C++17)

Содержание

[править]Синтаксис

ограничение-типа (необязательно)auto (1) (начиная с C++11)
ограничение-типа (необязательно)decltype(auto) (2) (начиная с C++14)
ограничение-типа(начиная с C++20) имя концепта, необязательно уточнённое, за которым может следовать список аргументов шаблона, заключённый в <>
1) тип выводится с использованием правил для вывода аргумента шаблона.
2) тип decltype(выражение), где выражение это инициализатор или то, что используется в операторах возврата.

Заполнитель auto может сопровождаться модификаторами, такими как const или &, которые будут участвовать в выводе типа. Заполнитель decltype(auto) должен быть единственным компонентом объявленного типа.(начиная с C++14)

[править]Объяснение

Спецификатор типа заполнителя может появляться в следующих контекстах:

  • в последовательности спецификатора типа переменной: auto x = выражение; в качестве спецификатора типа. Тип выводится из инициализатора.
    Если спецификатором типа заполнителя является autoили ограничение-типаauto(начиная с C++20), тип переменной выводится из инициализатора с использованием правил для вывода аргумента шаблона из вызова функции (для подробностей смотрите вывод аргумента шаблона — другие контексты).
    Например, при данном constauto& i = выражение;, тип i в точности совпадёт с типом аргумента u в воображаемом шаблоне template<class U>void f(const U& u), если вызов функции f(выражение) был скомпилирован. Следовательно, auto&& может быть выведено либо как ссылка lvalue, либо как ссылка rvalue в соответствии с инициализатором, который используется в цикле for на основе диапазона.

    Если спецификатор типа заполнителя имеет вид decltype(auto)или ограничение-типаdecltype(auto)(начиная с C++20), выведенный тип это decltype(выражение), где выражение это инициализатор.

    (начиная с C++14)

    Если спецификатор типа заполнителя используется для объявления нескольких переменных, выведенные типы должны совпадать. Например, объявление auto i =0, d =0.0; некорректно, а объявление auto i =0, *p =&i; правильно и auto выводится как int.

  • в идентификаторе типа выражения new. Тип выводится из инициализатора. Для new Tинициализатор (где T содержит тип-заполнитель, инициализатор является либо инициализатором в скобках, либо списком инициализаторов в фигурных скобках), тип T выводится, как для переменной x в придуманном объявлении T x инициализатор;.
  • (начиная с C++14) в возвращаемом типе функции или лямбда-выражения: auto& f();. Тип возвращаемого значения выводится из операнда не отброшенного(начиная с C++17)оператора return.
    Смотрите функция — вывод типа возвращаемого значения.
  • (начиная с C++17) в объявлении параметра шаблона не типа: template<auto I>struct A;. Его тип выводится из соответствующего аргумента.

Спецификатор auto может также появляться в спецификаторе простого типа явного преобразование типа: auto(выражение) и auto{выражение}. Его тип выводится из выражения.

(начиная с C++23)

Кроме того, autoи ограничение-типаauto(начиная с C++20) может появляться в:

(начиная с C++14)

Ограничение типа

Если присутствует ограничение-типа, пусть T будет типом, выведенным для заполнителя, ограничение-типа вводит выражение ограничения следующим образом:

  • Если ограничение-типа это Concept<A1, ..., An>, то выражение ограничения имеет вид Concept<T, A1, ..., An>;
  • иначе (ограничение-типа это Concept без списка аргументов), выражением ограничения является Concept<T>.

Вывод невозможен, если выражение ограничения недопустимо или возвращает false.

(начиная с C++20)

[править]Примечание

До C++11, auto имел семантику спецификатора длительности хранения.

Смешивание auto переменных и функций в одном объявлении, как в auto f()->int, i =0; не допускается.

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

auto(*p)()->int;// объявляет p как указатель на функцию, возвращающую intauto(*q)()->auto= p;// объявляет q как указатель на функцию, возвращающую T,// где T выводится из типа p

Спецификатор auto также может использоваться в объявлении структурной привязки.

(начиная с C++17)

Ключевое слово auto также может использоваться в спецификаторе-вложенного-имени. Спецификатор-вложенного-имени в форме auto:: это заполнитель, который заменяется классом или типом перечисления в соответствии с правилами вывода заполнителя ограниченного типа.

(ТС концепций)
Макрос Тестирования функциональностиЗначениеСтандартФункциональность
__cpp_decltype_auto201304L(C++14)decltype(auto)

[править]Пример

#include <iostream>#include <utility>   template<class T, class U>auto add(T t, U u){return t + u;}// возвращаемый тип это тип operator+(T, U)   // идеальная переадресация вызова функции должна использовать decltype(auto)// в случае, если вызываемая функция возвращает по ссылкеtemplate<class F, class... Args> decltype(auto) PerfectForward(F fun, Args&&... args){return fun(std::forward<Args>(args)...);}   template<auto n>// Автоматическое объявление параметра C++17auto f()->std::pair<decltype(n), decltype(n)>// auto не может вывести из списка// инициализации в скобках{return{n, n};}   int main(){auto a =1+2;// тип a равен intauto b = add(1, 1.2);// тип b равен double static_assert(std::is_same_v<decltype(a), int>); static_assert(std::is_same_v<decltype(b), double>);   auto c0 = a;// тип c0 равен int, содержит копию a decltype(auto) c1 = a;// тип c1 равен int, содержит копию a decltype(auto) c2 =(a);// тип c2 равен int&, псевдоним astd::cout<<"до модификации через c2, a = "<< a <<'\n';++c2;std::cout<<" после модификации через c2, a = "<< a <<'\n';   auto[v, w]= f<0>();//объявление структурной привязки   auto d ={1, 2};// OK: тип d это std::initializer_list<int>auto n ={5};// OK: тип n это std::initializer_list<int>// auto e{1, 2}; // Ошибка начиная с DR n3922, std::initializer_list<int> передauto m{5};// OK: тип m это int начиная с DR n3922, initializer_list<int> перед// decltype(auto) z = { 1, 2 } // Ошибка: {1, 2} не является выражением   // auto обычно используется для безымянных типов, таких как типы лямбда-выраженияauto lambda =[](int x){return x +3;};   // auto int x; // правильно C++98, ошибка с C++11// auto x; // правильно C, ошибка в C++   [](...){}(c0, c1, v, w, d, n, m, lambda);// подавляет предупреждения о// "неиспользуемой переменной"}

Возможный вывод:

до модификации через c2, a = 3 после модификации через c2, a = 4

[править]Отчёты о дефектах

Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:

Номер Применён Поведение в стандарте Корректное поведение
CWG 1265 C++11 спецификатор auto можно использовать для объявления функции
с конечным возвращаемым типом и определения переменной в
одном операторе объявления
запрещено
CWG 1346 C++11 список выражений в скобках не может быть присвоен автоматической переменной разрешено
CWG 1347 C++11 объявление со спецификатором auto может определять две переменные
с типами T и std::initializer_list<T> соответственно
запрещено
CWG 1852 C++14 спецификатор auto в decltype(auto) также был заполнителем не заполнитель
в данном случае
close