The auto
keyword has been part of C++ since C++11, and its role has developed somewhat since then. This article intends to cover all the use cases of auto
, including syntax that is new in the upcoming C++23 standard. The list of uses covered is:
- Type deduction for variable definitions
- References to other entities
- Deduction of a function’s return type
- Generic lambdas and functions
- Making a temporary copy of an entity
1. Type deduction for variable definitions
The auto
keyword an be used instead of a type specifier in all cases where a definition is also an initialization. Use of a *
indicates that we know we are initializing a pointer type:
auto i = 1;
auto *s{ "hello" };
auto p = std::make_unique<Class>("param1", "param2");
By the way, in cases where the RHS is an entity such as another variable (including the return value of a function) or a reference, a copy is made (according to the copy semantics of the entity itself).
2. References to other entities
The qualifiers const
, &
and &&
can be used with auto
; use of them is independent of the type of the RHS.
const auto& ri = i; // ri cannot be modified
auto&& r = 3 + 4; // r is an r-value reference
To give the LHS the same qualifiers as the RHS, the curious-looking construct decltype(auto)
can be used:
decltype(auto) rri{ ri };
rri = 2; // rri, ri and i have value 2
It is not always obvious which of auto&
and decltype(auto)
needs to be used; as a rule of thumb remember that decltype is more flexible:
auto& print = std::cout;
decltype(auto) newline = &std::endl<char, std::char_traits<char>>;
print << "Hello, world!" << newline;
3. Deduction of a function’s return type
It used to be necessary to use decltype()
and trailing return type syntax to avoid specifying the return type of a function explicitly, but now plain auto
can be used in the function declaration or definition. There is a caveat: such a function must specify the definition before use.
auto f() {
return 42;
}
Another restriction is that all the return
expressions of a function defined with auto
as the return type must evaluate to the same type. Even decltype(auto)
can be used as a return type in Modern C++, this preserves constant/reference qualifiers (should auto-deducing a complex reference return type be necessary, for example).
4. Generic lambdas and functions
Lambdas were covered in a previous mini-series, while generic functions no longer needing the template<>
keyword are new to C++20:
void g(auto a, auto b) {
std::cout << "a = " << a << "\nb = " << b << '\n';
}
No checks are made on the types of parameters declared with auto
, if these types should be constrained then template<>
should be used together with C++ concepts.
Parameter packs are also supported, for example:
void logv(std::string_view fmt, auto&&... params) {
auto args = std::make_format_args(std::forward<decltype(params)>(params)...);
std::cerr << std::vformat(fmt, args) << '\n';
}
// ...
logv("Hello {0} {1}!", 2, 'U');
Output is: Hello 2 U!
Note that use of decltype(params)
is necessary to infer the type for std::forward
.
5. Making a temporary copy of an entity
For the case where a parameter passed to a function must not be a reference (if it might be modified by the function call, for example), but the desired argument is a reference (such as container.front()
) this entity can be simply wrapped as auto{ ... }
in order to obtain a temporary. The only difference to defining a new variable using auto
beforehand is that its lifetime is the scope of the function call; there is no need to create a sub-scope in the caller environment.
std::vector<std::string_view> vsv{ "apple", "banana", "apple", "pear", "banana", "pear", "apple" };
vsv.erase(std::remove(begin(vsv), end(vsv), auto{ vsv.front() }), end(vsv));
// vsv is now correctly { "banana", "pear", "banana", "pear" }
This usage may find uses in other applications too, removing constant or reference qualifiers when passing exotic objects to template functions.
I hope I haven’t missed any uses of auto
; if you know of any others, or have another example to share, please leave a comment.