C++: C++17/20 New Features
Last updated: 2026-08-26
In lesson 47, we learned about template metaprogramming.
Now, we'll learn about C++17 and C++20 new features.
These new features make C++ more concise, safer, and more powerful.
1. C++17 New Features
(1) 1.1 Structured Binding
Feature: Conveniently unpack from tuple, pair, and struct.
Example: Structured Binding (Difficulty ⭐)
▶ Example 2: Code Example (Difficulty ⭐)
#include <iostream>
#include <tuple>
int main() {
std::tuple<int, std::string, double> t = {1, "Hello", 3.14};
// C++17: Structured binding
auto [id, name, score] = t;
std::cout << "ID: " << id << std::endl;
std::cout << "Name: " << name << std::endl;
std::cout << "Score: " << score << std::endl;
return 0;
}
Output:
ID: 1
Name: Hello
Score: 3.14
(2) 1.2 if constexpr
Feature: Compile-time if, selectively compiling code based on conditions.
Example: if constexpr (Difficulty ⭐⭐)
#include <iostream>
#include <type_traits>
template<typename T>
auto process(T value) {
if constexpr (std::is_integral_v<T>) {
return value * 2; // Integer: double it
} else {
return value; // Other: return as-is
}
}
int main() {
std::cout << process(10) << std::endl; // 20
std::cout << process(3.14) << std::endl; // 3.14
return 0;
}
(3) 1.3 Fold Expressions
Feature: Simplify variadic templates.
Example: Fold Expression (Difficulty ⭐⭐)
#include <iostream>
template<typename... Args>
void print(Args... args) {
(std::cout << ... << args) << std::endl; // Fold expression
}
int main() {
print(1, 2, 3, 4, 5); // Output: 12345
return 0;
}
(4) 1.4 Other C++17 Features
| Feature | Description |
|---|---|
std::optional |
A value that may be empty |
std::variant |
Type-safe union |
std::any |
Any type |
std::string_view |
String view (zero-copy) |
| Class template argument deduction | No need to write pair<int, int> anymore |
2. C++20 New Features
(1) 2.1 Concepts
Feature: Constrain template parameters for friendlier error messages.
Example: Constraining Templates with Concepts (Difficulty ⭐⭐⭐)
#include <iostream>
#include <concepts>
// Constrain T to be an integral type
template<typename T>
requires std::integral<T>
T doubleValue(T x) {
return x * 2;
}
int main() {
std::cout << doubleValue(10) << std::endl; // 20
// std::cout << doubleValue(3.14) << std::endl; // ❌ Compile error (clear)
return 0;
}
(2) 2.2 Ranges Library
Feature: A more concise way to call STL algorithms.
Example: Using ranges (Difficulty ⭐⭐)
#include <iostream>
#include <ranges>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
// C++20: ranges
auto result = v | std::views::filter([](int x) { return x % 2 == 0; })
| std::views::transform([](int x) { return x * 10; });
for (int x : result) {
std::cout << x << " "; // Output: 20 40
}
std::cout << std::endl;
return 0;
}
(3) 2.3 Coroutines
Feature: Support for coroutines (functions that can pause/resume).
Example: Simple Coroutine (Difficulty ⭐⭐⭐⭐)
#include <iostream>
#include <coroutine>
// Coroutines in C++20 are complex; specific implementation omitted here
// Concept: coroutines can pause execution and resume later
int main() {
// C++20 coroutine example (simplified)
std::cout << "C++20 Coroutines" << std::endl;
return 0;
}
(4) 2.4 Other C++20 Features
| Feature | Description |
|---|---|
| Modules | Replace header files, faster compilation |
| Coroutines | Asynchronous programming |
| Date library (chrono extensions) | Better date/time handling |
| Format library (format) | Python-style formatting |
| Spaceship operator (<=>) | Three-way comparison |
3. Choosing a Standard
(1) 3.1 Which Standard Should You Use?
| Standard | Recommendation |
|---|---|
| C++11 | Minimum standard, must use |
| C++14 | Minor improvements, recommended |
| C++17 | Many practical features, highly recommended |
| C++20 | Latest features, use cautiously (compiler support may be incomplete) |
4. Practice: Refactoring Code with C++17
▶ Example 1: Simplifying Code with Structured Binding (Difficulty ⭐⭐)
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<int, std::string> students = {{1, "Zhang San"}, {2, "Li Si"}};
// C++17: Structured binding to iterate map
for (const auto& [id, name] : students) {
std::cout << id << ": " << name << std::endl;
}
return 0;
}
Output:
1: Zhang San
2: Li Si
▶ Example 3: auto Type Deduction (Difficulty ⭐)
#include <iostream>
#include <vector>
int main() {
auto x = 10; // int
auto y = 3.14; // double
auto name = "Hello"; // const char*
std::vector<int> nums = {1, 2, 3, 4, 5};
auto it = nums.begin(); // vector<int>::iterator
std::cout << "x = " << x << std::endl;
std::cout << "y = " << y << std::endl;
std::cout << "name = " << name << std::endl;
return 0;
}
Output:
x = 10
y = 3.14
name = Hello
Expected output:
x = 10
y = 3.14
name = Hello
❓ FAQ
bash g++ -std=c++17 main.cpp g++ -std=c++20 main.cpp 📖 Summary
| Standard | Key Features |
|---|---|
| C++17 | Structured binding, if constexpr, fold expressions |
| C++20 | Concepts, Ranges, coroutines, modules |
📝 Exercises
-
Basic (Difficulty ⭐): Rewrite an old-style C++ code snippet (with explicit types, traditional for, NULL) using auto, range-based for, and nullptr.
-
Intermediate (Difficulty ⭐⭐): Use structured binding (C++17) to unpack a pair or tuple return value, and compare it with the traditional .first/.second approach.
-
Challenge (Difficulty ⭐⭐⭐): Use if constexpr (C++17) to implement compile-time branching — write a function template that applies different processing logic for integer types and floating-point types.
- C++11: auto/nullptr/range-for/lambda/smart pointers
- C++14: generic lambda/make_unique
- C++17: structured binding/if constexpr/string_view/filesystem
- C++20: modules/coroutines/concepts/Ranges
- This course uses C++17, balancing new features and compatibility
Next lesson: Performance Optimization (#49)