auto i = 42; // int
auto it = v.begin(); // iterator type deduced
auto f = [](int x){return x;};
C++
Topics in this category
Casting & Conversions
Compilation & Linking
Concepts & Constraints
Concurrency
Const Correctness
Constexpr & Compile-Time
Coroutines
Enums & Enum Classes
Exception Handling
I/O Streams
Lambda Expressions
Memory Management
Modern C++
Move Semantics
Namespaces
OOP & Classes
Operator Overloading
Preprocessor & Macros
RAII & Smart Pointers
Ranges & Views
C++
Type Deduction & auto
auto lets the compiler deduce a variable's type from its initializer, reducing verbosity and coupling to exact types. auto x = expr; gives x the type of expr (with top-level const and references stripped unless specified). It's especially useful for complex types like iterators and lambdas.
Real-world example
Using auto for an iterator avoids spelling out std::vector<std::string>::const_iterator.
Templates
Modern C++
Type Deduction & auto
auto deduces a value type (a copy, dropping references/top-level const). auto& deduces a (mutable) reference to the source, avoiding a copy and allowing modification. const auto& deduces a const reference—no copy, read-only—ideal for iterating large objects without copying. Choosing the right form controls copies and mutability.
for (auto x : v) // copies each element
for (auto& x : v) // reference, can modify
for (const auto& x : v) // no copy, read-only
Real-world example
Switching a range-for from auto to const auto& stops copying large strings on each iteration.
References & Pointers
Type Deduction & auto
Type Deduction & auto
When you call a template function, the compiler deduces the template parameters from the argument types, following rules similar to auto. For a parameter T (by value), references and top-level const are stripped; for T& the reference is kept; for T&& (a forwarding reference) it deduces lvalue/rvalue-ness. Deduction lets you call templates without specifying types explicitly.
template <class T> void f(T x);
f(42); // T = int
f("hi"); // T = const char*
Real-world example
A generic max() deduces its element type from the arguments, so callers don't specify it.
Templates
Move Semantics
Type Deduction & auto
decltype(expr) yields the declared type of an expression without evaluating it, preserving references and const exactly (unlike auto, which strips them for value deduction). It's used to declare variables or return types that must match an expression's type precisely, especially in templates and trailing return types.
int x = 0; int& r = x;
auto a = r; // int (copy)
decltype(r) b = x; // int& (reference preserved)
Real-world example
decltype captures the exact type of a container element to declare a matching variable in generic code.
Templates
Type Deduction & auto
Type Deduction & auto
decltype(auto) (C++14) deduces a type using decltype rules rather than auto rules, so it preserves references and const. It's used mainly for return types of forwarding/wrapper functions that must return exactly what an inner call returns (a reference if the inner returns a reference), which plain auto would incorrectly turn into a value.
template <class F, class... A>
decltype(auto) call(F f, A&&... a) {
return f(std::forward<A>(a)...); // preserves ref-ness
}
Real-world example
A perfect-forwarding wrapper uses decltype(auto) so it returns a reference when the wrapped function does.
Templates
Move Semantics
Type Deduction & auto
Since C++14, a function can declare auto as its return type and the compiler deduces it from the return statements (which must all deduce the same type). It reduces verbosity for complex return types and is required for some generic code. Use a trailing return type or decltype(auto) when you need precise control.
auto add(int a, int b) { return a + b; } // returns int
Real-world example
A helper returning a complex iterator type uses auto so its signature stays readable.
Templates
Type Deduction & auto
Type Deduction & auto
auto uses value (by-copy) deduction like a by-value template parameter, so it drops references and top-level const to give an independent copy. This is usually desirable, but it's a problem when you intended to alias or avoid copying—then you must write auto&, const auto&, or use decltype(auto). Forgetting this silently introduces copies.
const int& getRef();
auto x = getRef(); // int copy (const & dropped)
const auto& y = getRef(); // const int& (no copy)
Real-world example
A subtle performance bug: auto copies a large object returned by const-reference until changed to const auto&.
References & Pointers
Type Deduction & auto
Type Deduction & auto
Benefits: less verbose code, fewer explicit type mismatches, easier refactoring, and readable handling of complex types (iterators, lambdas). Risks: reduced readability if the deduced type is unclear, accidental copies (auto vs auto&), and unexpected types from expressions. Use auto where the type is obvious or unwieldy, and be explicit when clarity or exact type matters.
auto total = items.size(); // std::size_t, not int
Real-world example
Overusing auto in an API makes types hard to read; using it for local iterators improves clarity.
Type Deduction & auto
Modern C++
Type Deduction & auto
CTAD (C++17) lets you construct a class template without specifying its template arguments—the compiler deduces them from the constructor arguments, similar to function template deduction. It reduces verbosity for types like std::pair, std::vector, and std::lock_guard. Deduction guides can customize how arguments map to template parameters.
std::pair p(1, 2.0); // pair<int, double> deduced
std::vector v{1, 2, 3}; // vector<int>
std::lock_guard g(mtx); // lock_guard<mutex>
Real-world example
CTAD lets you write std::lock_guard g(mtx) without repeating the mutex type.
Templates
STL
Type Deduction & auto
A forwarding reference is a function template parameter of the form T&& where T is deduced. It binds to both lvalues and rvalues: for an lvalue argument T deduces to U& (reference collapsing makes the param U&), and for an rvalue T deduces to U (param U&&). Combined with std::forward, it enables perfect forwarding of value category.
template <class T>
void wrapper(T&& x) { inner(std::forward<T>(x)); }
Real-world example
A factory forwards its arguments to a constructor preserving whether each was an lvalue or rvalue.
Move Semantics
Templates
Type Deduction & auto