auto & decltype

Some C++ types are long and ugly — iterator types, template results, lambda types. auto lets the compiler figure them out for you, and decltype reports the exact type of an expression when you need precision. Used well, they make code shorter and safer; used carelessly, they hide important detail. This lesson teaches you when each one earns its keep.

Learn auto & decltype in our free C++ course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick recall.

Part of the free C++ course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Imagine filling out a form. With explicit types you write the full label every time: "this box holds a 32-bit signed integer". With auto you instead say "whatever fits what I'm putting in" — you hand over a value and the form figures out the right box. It's not weaker typing : the box still has exactly one fixed type, you just let the value decide it. decltype is like asking a clerk "what type is that field over there?" — it tells you the precise declared type of something that already exists, without touching it.

1. auto: Deduce the Type

auto asks the compiler to deduce a variable's type from its initializer. It's still strongly, statically typed — once deduced, the type is locked in. The classic payoff is iterators: instead of writing , you write auto . Note that an auto variable must be initialized, since there's nothing to deduce from otherwise.

2. auto Copies — Use auto& to Avoid It

Here's the subtle part: plain auto deduces by value , so it makes a copy and strips away references and top-level const . In a range-based for loop that means for (auto n : v) modifies copies, not the real elements. Use auto& to bind a reference (to modify the originals) or const auto& to read efficiently without copying.

Your turn. The loop below should double each price in place . Fill in the blank with the right form of auto :

These lines declare a value with auto , derive a decltype type from it, and print. Put them in order:

Open main (D), let price deduce to double (B), declare tax with the same type via decltype(price) (A), print the sum 5.25 (C), then return 0; (E) and close (F). decltype(price) needs price to exist first.

3. decltype: the Exact Type of an Expression

Where auto deduces from a value and strips references and const, decltype(expr) reports the exact declared type of an expression — including const and references — and it does not evaluate the expression. This makes it the precise tool when you must mirror the type of something that already exists, such as the result type of a + b in a template.

4. Deduced Return Types

Since C++14, a function can use auto as its return type and the compiler deduces it from the return statements — invaluable for templates where the result type depends on the inputs. The older trailing return type syntax, auto f(...) -> decltype(...) , spells the type out explicitly using decltype , which is occasionally clearer or required.

Plain auto follows the same rules as template argument deduction: it deduces by value , dropping top-level const and references. You opt back in explicitly:

decltype(auto) is a special return-type form that uses decltype's rules instead of auto's, so it preserves references and const. It's mainly for generic wrappers that must forward an expression's exact type:

Predict the output before revealing the answer.

1 — plain auto copies each element, so n += 100 changes copies, not the vector. Use auto& to actually modify it.

3 — 7 / 2 is integer division giving an int 3, so x is deduced as int . auto doesn't change the math.

99 — decltype(a) is int , so b is an int& bound to a . Assigning to b updates a .

Put const auto& and structured bindings to work iterating a map, and let auto hold your running total.

Practice quiz

What does 'auto' do in 'auto x = 5;'?

  • Makes x dynamically typed
  • Makes x a reference
  • Deduces x's type (int) from the initializer at compile time
  • Defers x's type until runtime

Answer: Deduces x's type (int) from the initializer at compile time. auto deduces the type from the initializer; the type is still fixed and checked at compile time.

In a range loop, 'for (auto n : v) n *= 10;' fails to change the vector because:

  • Plain auto deduces by value, so n is a copy
  • auto is read-only
  • The loop never runs
  • 10 is too large

Answer: Plain auto deduces by value, so n is a copy. Plain auto copies each element; use 'auto&' to bind a reference and modify the originals.

Which form modifies the container's elements AND avoids copying when only reading is needed?

  • auto& for both
  • const auto for both
  • decltype(auto) only
  • auto for writing; const auto& for reading

Answer: auto for writing; const auto& for reading. Use auto& to modify originals, and const auto& to read big objects without copying.

What does plain 'auto' drop during deduction?

  • Nothing
  • Top-level const and references
  • Only references
  • Only const

Answer: Top-level const and references. Plain auto deduces by value, stripping top-level const and references; opt back in with auto&, const auto&, etc.

How does decltype(expr) differ from auto?

  • It reports the exact declared type, keeping const and references
  • It evaluates the expression
  • It only works on integers
  • It is the same as auto

Answer: It reports the exact declared type, keeping const and references. decltype gives the precise declared type (including const and &) without evaluating the expression.

What is the type of x in 'auto x = 7 / 2;' and what does it print?

  • double, 3.5
  • int, 4
  • int, 3
  • float, 3.5

Answer: int, 3. 7 / 2 is integer division giving int 3; auto deduces int and doesn't change the math.

Given 'int a = 5; decltype((a)) c = a;', what is c's type?

  • int (a copy)
  • int& (a reference to a)
  • const int
  • double

Answer: int& (a reference to a). The extra parentheses make decltype((a)) yield int& — a reference — so assigning to c changes a.

What does the trailing-return syntax 'auto add(A a, B b) -> decltype(a + b)' do?

  • Always returns int
  • Returns void
  • Forbids deduction
  • Spells out the return type explicitly using decltype of the expression

Answer: Spells out the return type explicitly using decltype of the expression. It declares the return type after the parameters using decltype, useful when the result type depends on the arguments.

Why does 'auto x;' fail to compile?

  • auto is reserved
  • There is no initializer for the compiler to deduce the type from
  • x must be uppercase
  • auto needs a semicolon

Answer: There is no initializer for the compiler to deduce the type from. An auto variable must be initialized, since the type is deduced from the initializer.

What is decltype(auto) mainly used for?

  • Looping faster
  • Declaring globals
  • Forwarding an expression's exact type (preserving references/const) in generic code
  • Disabling const

Answer: Forwarding an expression's exact type (preserving references/const) in generic code. decltype(auto) uses decltype's rules so a generic return can preserve the exact type and value category of an expression.