1. Problem It Solves
Plain auto return deduction normally produces a value and drops references. C++14 decltype(auto) applies decltype rules to the return expression, allowing a forwarding or accessor function to preserve a reference.
Focus on the smallest useful form, its observable behavior, and its safety boundary.
2. Prerequisites
Days 2 and 12:
decltypeexpression rules, references, value categories, and function return deduction.
3. Core Idea
The exact spelling of the return expression matters. Returning a parenthesized lvalue such as (values.front()) deduces an lvalue reference, so the caller can reach the original element.
Identify the objects and types, today's operation, and the printed result. This connects syntax to behavior.
4. Minimal Syntax
decltype(auto) first(std::vector<int>& values) {
return (values.front());
}5. How It Works
The accessor evaluates an lvalue expression that names an element owned by the vector.
decltype(auto)preserves the expression category and deducesint&instead of copying anint.Assigning through the returned reference changes the first element stored in the original vector.
6. Common Mistakes
Returning a reference to a local variable or temporary preserves a dangling reference rather than making it safe.
Do not copy the pattern without checking the exact return expression, its value category, and whether the referred object outlives the returned reference. A program may compile while still having the wrong lifetime, ownership, invalidation, ordering, or performance behavior.
7. When to Use It
Use it when an accessor or forwarding wrapper must deliberately preserve value versus reference behavior.
Avoid it when a value return is safer and cheap, or the lifetime behind the reference is not guaranteed.
8. Simple Example
The function first returns the vector's first element by reference. Binding the result with decltype(auto) and assigning 99 demonstrates that no copy was made.
The .cpp file uses fixed data. Predict its output, compile it, then change one value and test the prediction.
Complete sample code
Source file
cpp14/13_decltype_auto_preserve_reference/main.cpp
#include <iostream>
#include <vector>
decltype(auto) first(std::vector<int>& values) {
return (values.front()); // int& because the expression is an lvalue
}
int main() {
std::vector<int> values{10, 20, 30};
decltype(auto) element = first(values);
element = 99;
std::cout << "first: " << values.front() << "\n";
}
9. Key Takeaways
decltype(auto)preserves more type information, so it also preserves lifetime hazards.The exact spelling of the return expression matters. Returning a parenthesized lvalue such as
(values.front())deduces an lvalue reference, so the caller can reach the original element.The compiler or library follows a precise rule; verify the exact return expression, its value category, and whether the referred object outlives the returned reference.
Prefer the smallest form that communicates intent and measure costs when performance matters.
10. Self-Check Questions
Easy — What is the main purpose of decltype(auto) and Preserving References?
Medium — After assigning through the result of
first(values), what doesvalues.front()contain?Hard — How would removing the parentheses in a return of a plain named variable change
decltype(auto)deduction underdecltyperules?