Spec-Zone.ru › C++

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

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

Синтаксис

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

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

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

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

Вывод завершается неудачей, если выражение-ограничение некорректно или возвращает false.

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

Пояснение

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

Объявления параметров

В следующих объявлениях параметров тип объявляемого параметра может иметь синтаксис (1):

  • Если параметр лямбда-выражения имеет тип-заполнитель, лямбда-выражение является обобщённой лямбдой.
(начиная с C++14)
  • Если нетиповой параметр шаблона имеет тип-заполнитель, его тип выводится из соответствующего аргумента шаблона.
(начиная с C++17)
  • Если параметр объявления функции имеет тип-заполнитель, объявляется сокращённый шаблон функции.
(начиная с C++20)

Объявления функций

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

Тип-заполнитель может встречаться в спецификаторах объявления или спецификаторах типа объявленного типа возвращаемого значения декларатора функции. В этом случае применяется вывод типа возвращаемого значения.

(начиная с C++14)
auto f() -> int; // OK: f returns int
auto g() { return 0.0; } // OK since C++14: g returns double
auto h(); // OK since C++14: h’s return type will be deduced when it is defined

Объявления переменных

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

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

// “auto”s in declaration specifiers
auto x = 5; // OK: x has type int
const auto *v = &x, u = 6; // OK: v has type const int*, u has type const int
static auto y = 0.0; // OK: y has type double

auto f() -> int;
auto (*fp)() -> auto = f; // OK: the “auto” in the trailing return type
                          // can be deduced from f

Объявления структурированных привязок

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

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

Выражения new

Тип-заполнитель можно использовать в последовательности спецификаторов типа в type-id выражения new. В таком type-id тип-заполнитель должен встречаться как один из спецификаторов типа в последовательности спецификаторов типа или в завершающем типе возвращаемого значения, который задаёт тип, заменяющий такой спецификатор типа.

Приведение в функциональном стиле

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

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

Примечания

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

Программа, использующая тип-заполнитель в контексте, явно не указанном выше, некорректна.

Если объявление объявляет несколько сущностей и последовательность спецификаторов объявления использует тип-заполнитель, программа некорректна, если выполняется хотя бы одно из следующих условий:

  • Некоторые из объявленных сущностей не являются переменными.
  • Тип, заменяющий тип-заполнитель, неодинаков при каждом выводе.
auto f() -> int, i = 0; // Error: declares a function and a variable with “auto”
auto a = 5, b = {1, 2}; // Error: different types for “auto”

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

(Техническая спецификация concepts)
Макрос проверки наличия функции Значение Стандарт Функция
__cpp_decltype_auto 201304L (C++14) decltype(auto)

Ключевые слова

auto, decltype

Пример

#include <iostream>
#include <utility>

template<class T, class U>
auto add(T t, U u) { return t + u; } // the return type is the type of operator+(T, U)

// perfect forwarding of a function call must use decltype(auto)
// in case the function it calls returns by reference
template<class F, class... Args>
decltype(auto) PerfectForward(F fun, Args&&... args) 
{ 
    return fun(std::forward<Args>(args)...); 
}

template<auto n> // C++17 auto parameter declaration
auto f() -> std::pair<decltype(n), decltype(n)> // auto can't deduce from brace-init-list
{
    return {n, n};
}

int main()
{
    auto a = 1 + 2;          // type of a is int
    auto b = add(1, 1.2);    // type of b is double
    static_assert(std::is_same_v<decltype(a), int>);
    static_assert(std::is_same_v<decltype(b), double>);
    
    auto c0 = a;             // type of c0 is int, holding a copy of a
    decltype(auto) c1 = a;   // type of c1 is int, holding a copy of a
    decltype(auto) c2 = (a); // type of c2 is int&, an alias of a
    std::cout << "before modification through c2, a = " << a << '\n';
    ++c2;
    std::cout << " after modification through c2, a = " << a << '\n';
    
    auto [v, w] = f<0>(); //structured binding declaration
    
    auto d = {1, 2}; // OK: type of d is std::initializer_list<int>
    auto n = {5};    // OK: type of n is std::initializer_list<int>
//  auto e{1, 2};    // Error as of DR n3922, std::initializer_list<int> before
    auto m{5};       // OK: type of m is int as of DR n3922, initializer_list<int> before
//  decltype(auto) z = { 1, 2 } // Error: {1, 2} is not an expression
    
    // auto is commonly used for unnamed types such as the types of lambda expressions
    auto lambda = [](int x) { return x + 3; };
    
//  auto int x; // valid C++98, error as of C++11
//  auto x;     // valid C, error in C++
    
    [](...){}(c0, c1, v, w, d, n, m, lambda); // suppresses "unused variable" warnings
}

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

before modification through c2, a = 3
 after modification through c2, a = 4

Отчёты об ошибках

Следующие отчёты об ошибках, меняющие поведение, были применены ретроспективно к ранее опубликованным стандартам C++.

DR Применяется к Опубликованное поведение Правильное поведение
CWG 1265 C++11 спецификатор auto можно было использовать для объявления функции с завершающим
типом возвращаемого значения и определения переменной в одном объявлении
запрещено
CWG 1346 C++11 список выражений в скобках нельзя было присвоить переменной auto разрешено
CWG 1347 C++11 объявление со спецификатором auto могло определять две переменные
с типами T и std::initializer_list<T> соответственно
запрещено
CWG 1852 C++14 спецификатор auto в decltype(auto) также являлся заполнителем в этом случае
не является заполнителем
CWG 1892 C++11 тип возвращаемого значения в type-id указателя на функцию мог быть auto запрещено
CWG 2476 C++11 решение CWG issue 1892 запрещало вывод
типа возвращаемого значения переменных-указателей на функции из инициализаторов
разрешено

Ссылки

  • Стандарт C++23 (ISO/IEC 14882:2024):
    • 9.2.9.6 Спецификаторы-заполнители типа [dcl.spec.auto]
  • Стандарт C++20 (ISO/IEC 14882:2020):
    • 9.2.8.5 Спецификаторы-заполнители типа [dcl.spec.auto]
  • Стандарт C++17 (ISO/IEC 14882:2017):
    • 10.1.7.4 Спецификатор auto [dcl.spec.auto]
  • Стандарт C++14 (ISO/IEC 14882:2014):
    • 7.1.6.4 Спецификатор auto [dcl.spec.auto]
  • Стандарт C++11 (ISO/IEC 14882:2011):
    • 7.1.6.4 Спецификатор auto [dcl.spec.auto]

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/auto

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API