c++ – Type inference rules for the auto keyword

Question:

How is the type of an initialized variable determined when using the auto keyword?

In what cases will a variable turn out to be a constant, reference, pointer, or all this in various combinations?

How will additional guidelines, such as const auto , auto& , const auto& (and probably also similar with pointers, maybe even with double pointers, and with && ), affect these rules?

Answer:

The inference rules are very similar to those for functions like template <typename T> void foo(T) .

[const] [volatile] auto – will never be a reference, no cv qualifiers ( const , volatile ) are automatically added.

A special case – if such a variable is initialized = {a,b,c} – then the type will be [const] [volatile] std::initializer_list<T> .

[const] [volatile] auto & – cv-qualifiers are added automatically (except for the case when it is initialized with rvalue – then it will be an error without a 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 && – if at least one cv qualifier is specified, then it works by analogy with auto & , but for rvalues.

If no cv qualifiers are specified, then it works as a forwarding link:

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 && , like auto , can work with initializer_list :

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

In all cases above, if the variable is initialized with {a} (without = ), then auto behaves as if the initializer were = a . There must be only one item in curly braces.


auto can be referred to in more complex constructs: you can make pointers to auto , pointers to members, and references to them. Pointers to pointers, pointers to functions, etc. are allowed. But arrays with auto for some reason cannot be done.

If we make a pointer to auto , then cv-qualifiers are added automatically:

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

There is also decltype(auto) . It is similar to auto , but it cannot be referenced or referenced, and cv qualifiers cannot be specified.

It uses the same inference rules as decltype .

It is especially well suited for writing function wrappers:

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

Here, the return type of bar copied to foo , even if it is a reference.

Scroll to Top