Scott Meyers wrote in Effective Modern C++ (2014) that without a clear model of type deduction, effective modern C++ is impractical — there are too many contexts: function templates, auto, decltype, and since C++14 also decltype(auto).
That claim still holds for C++20 / C++23. The fundamental rules for template, auto, decltype, and decltype(auto) were not cancelled or simplified — language compatibility rests on them. Later standards added more places where deduction appears.
What landed from C++14 to C++20 / C++23
CTAD (C++17, improved in C++20)
Class template parameters can be deduced from constructor arguments:
std::pair p(10, 3.14); // std::pair<int, double>
std::vector v = {1, 2, 3}; // std::vector<int>
Abbreviated function templates via auto (C++20)
auto in a parameter list makes the function a template; the same deduction rules as ordinary function templates apply:
void print(auto val); // equivalent to template <typename T> void print(T val)
Concepts and constrained auto (C++20)
std::integral auto x = compute(); // type is deduced, but must be integral
Structured binding (auto [a, b] — C++17)
auto [id, name] = get_user();
Nuance: deduction applies to a hidden variable; a and b are aliases for elements, not separate declarations carrying those same specifiers.
auto in non-type template parameters (NTTP — C++17 / C++20)
template <auto Value>
struct ConstantHolder {};
Deducing this (C++23)
The object of the call can be an explicit first parameter; Self is deduced with const and value category in mind:
struct Widget {
template <typename Self>
void foo(this Self&& self) {
// Self depends on how the method was called
}
};
This cuts down duplicated const / & / && methods, but it requires a solid grasp of forwarding references and type deduction.
The core template / auto / decltype scenarios are in the note on the three pillars of deduction. CTAD and guides are covered separately; structured binding and deducing this continue in the following notes in this series.