Правила вывода типа для ключевого слова auto

118
17 марта 2022, 23:50

Как определяется тип инициализируемой переменной при использовании ключевого слова auto?

В каких случаях переменная окажется константной, ссылкой, указателем, или всё это в различных комбинациях?

Как повлияют на эти правила дополнительные указания, типа const auto, auto&, const auto& (и ещё наверное аналогичные с указателями, может даже с двойными указателями, и с &&)?

Answer 1

Правила вывода очень похожи на правила для функций вроде template <typename T> void foo(T).

[const] [volatile] auto - никогда не будет ссылкой, никакие cv-квалификаторы (const, volatile) автоматически не добавляются.

Особый случай - если такую переменную инициализировать = {a,b,c} - то тип будет [const] [volatile] std::initializer_list<T>.

[const] [volatile] auto & - cv-квалификаторы добавляются автоматически (кроме случая, когда его инициализируют rvalue - тогда без указания const будет ошибка).

int a = 1;
const int b = 1;
auto &x = a; // int &x
auto &y = b; // const int &y
auto &z = 1; // Ошибка, хотя `const int &z = 1` скомпилировалось бы.
const auto &w = 1; // const int &w

[const] [volatile] auto && - если указан хотя бы один cv-квалификатор, то работает по аналогии с auto &, но для rvalue.

Если cv-квалификаторы не указаны, то работает как forwarding ссылка:

MyClass a = 1;
const MyClass b = 1;
auto &&x = a; // MyClass &x
auto &&x = b; // const MyClass &x
auto &&x = MyClass(); // MyClass &&x
auto &&x = (const MyClass) MyClass(); // const MyClass &&x

[const] [volatile] auto &&, так же как и auto, умеет работать с initializer_list:

auto &&x = {1,2,3}; // std::initializer_list<int> &&

Во всех случаях выше, если переменную инициализировать {a} (без =), то auto ведет себя так же, как если бы инициализатор был = a. В фигурных скобках должен быть только один элемент.

auto может упоминаться в более сложных конструкциях: можно делать указатели на auto, указатели-на-члены, и ссылки на них. Разрешаются указатели на указатели, указатели на функции, и т.д. Но массивы с auto почему-то нельзя делать.

Если сделать указатель на auto, то cv-квалификаторы добавляются автоматически:

const int x = 1;
auto *y = &x; // const int *y

Есть еще decltype(auto). Он похож на auto, но на него нельзя формировать ссылки и указатели, и нельзя указывать cv-квалификаторы.

Он использует те же правила вывода, что и decltype.

Он особенно хорошо подходит для написания оберток для функций:

decltype(auto) foo(бла бла)
{
    return bar(бла бла);
}

Здесь возвращаемый тип bar копируется в foo, даже если это ссылка.

Answer 2
const int n = 5;
auto m = n;  // int    
const int& p = n;
auto q = p;   //int
const std::vector<int> v(1);
auto a = v[0];          //  int 
decltype(a) d ;          // int, тип сущности, именованной как d 
decltype(v[0]) b = 1;   //  const int& (возвращаемое значение
                        // std::vector<int>::operator[](size_type) const)    
decltype((a)) ref = a;  // int&, так как (a) является lvalue
auto value = ref;       //int
++ref;   // ошибка
++value; //правильно
READ ALSO
Есть ли разница между GCC(g++) и Visual Studio?

Есть ли разница между GCC(g++) и Visual Studio?

Есть пару вопросов от начинающего

152
Указатели, delete и nullptr

Указатели, delete и nullptr

Сап! Объясните максимально подробно, пожалуйста, что именно делают delete и nullptr для указателейВот код:

166
Что за стиль записи в структуре

Что за стиль записи в структуре

Так вот я не понимаю,зачем писать WNDCLASSEX после обЪявления структуры,вычитал где то что это создание объекта,то есть ,будто бы мы объявили WNDCLASSEX...

158
c++, нейронная сеть, перцептрон, xor, ошибка

c++, нейронная сеть, перцептрон, xor, ошибка

Пытаюсь писать простой перцептрон, который имеет только 2 вход и 1 выход и не имеет никаких скрытых слоевПерцептрон должен выполнять функцию...

103