Modern C++ Cheat Sheet (C++11–C++23)
Quick reference for modern C++ features by standard — auto, lambdas, move semantics, structured bindings, concepts, and more.
C++11 essentials
cpp
// auto — type deduction
auto x = 42;
auto it = v.begin();
auto& ref = x;
// Range-based for
for (const auto& item : container) { }
for (auto& [k, v] : map) { } // structured bindings (C++17)
// Lambda
auto fn = [capture](params) -> RetType { body };
auto add = [](int a, int b){ return a + b; };
auto counter = [n=0]() mutable { return ++n; }; // C++14 init capture
// nullptr
int* p = nullptr; // not NULL or 0
// Move semantics
std::vector<int> a, b;
b = std::move(a); // a is now in valid but unspecified state
// Smart pointers
auto u = std::make_unique<T>(args);
auto s = std::make_shared<T>(args);
// Uniform initialization
std::vector<int> v{1, 2, 3};
struct Point { int x, y; };
Point p{1, 2};
// constexpr
constexpr int sq(int n) { return n * n; }
constexpr int val = sq(5); // 25 — compile-time
// static_assert
static_assert(sizeof(int) == 4, "need 32-bit int");
// override / final
struct Base { virtual void f(); };
struct Derived : Base { void f() override; };
struct Leaf : Derived { void f() final; };
// = delete / = default
struct NoCopy {
NoCopy(const NoCopy&) = delete;
NoCopy& operator=(const NoCopy&) = delete;
NoCopy() = default;
};
// Delegating constructors
struct Foo {
Foo() : Foo(0) {}
Foo(int n) : n_(n) {}
int n_;
};
// Variadic templates
template<typename... Args>
void log(Args&&... args) { (std::print("{} ", args), ...); } // fold expr (C++17)
// Type aliases
using Matrix = std::vector<std::vector<double>>;
template<typename T> using Vec = std::vector<T>;C++14 additions
cpp
// Generic lambdas
auto fn = [](auto x, auto y){ return x + y; };
// Lambda init capture
auto p = std::make_unique<int>(42);
auto fn = [p = std::move(p)]{ return *p; }; // capture by move
// Return type deduction
auto add(int a, int b) { return a + b; }
// std::make_unique
auto u = std::make_unique<int>(42);
// Binary literals and digit separators
int mask = 0b1111'0000;
long big = 1'000'000'000L;
// [[deprecated]]
[[deprecated("use new_func instead")]]
void old_func();C++17 additions
cpp
// Structured bindings
auto [a, b] = pair;
auto [key, val] = *map.find("x");
for (auto& [k, v] : map) { }
// if constexpr
template<typename T>
void f(T x) {
if constexpr (std::is_integral_v<T>) { /* int path */ }
else { /* other path */ }
}
// Inline variables
struct Foo { inline static int count = 0; };
// std::optional, std::variant, std::any
std::optional<int> opt = 42;
std::variant<int, std::string> v = "hi";
std::any a = 3.14;
// std::string_view — non-owning string reference
void f(std::string_view sv) { }
// Fold expressions
template<typename... Ts>
auto sum(Ts... args) { return (args + ...); }
// Class template argument deduction (CTAD)
std::pair p{1, 2.0}; // deduces pair<int, double>
std::vector v{1, 2, 3}; // deduces vector<int>
std::lock_guard lock(mtx); // deduces mutex type
// std::filesystem
namespace fs = std::filesystem;
fs::exists("path");
fs::recursive_directory_iterator("dir");
// Parallel algorithms
std::sort(std::execution::par, v.begin(), v.end());
// [[nodiscard]], [[maybe_unused]], [[fallthrough]]
[[nodiscard]] int compute();
[[maybe_unused]] int debug_val = compute();
switch(x) { case 1: [[fallthrough]]; case 2: break; }C++20 additions
cpp
// Concepts
template<std::integral T> T square(T n) { return n * n; }
void f(std::ranges::range auto r) { }
// Ranges and views
v | std::views::filter(pred) | std::views::transform(fn);
std::ranges::sort(v);
std::ranges::sort(v, {}, &S::field); // projection
// Coroutines
std::generator<int> gen() { co_yield 1; co_yield 2; }
// Three-way comparison (spaceship)
struct Foo { int n;
auto operator<=>(const Foo&) const = default;
};
// Designated initializers
struct Point { int x, y; };
Point p{.x = 1, .y = 2};
// Modules (compiler support required)
import std;
export module mymodule;
// std::format
std::string s = std::format("{:.2f}", 3.14);
// consteval — compile-time only
consteval int sq(int n) { return n * n; }
// std::span — non-owning contiguous range
void f(std::span<int> data) { }
// Abbreviated function templates
void f(auto x) { } // same as template<typename T> void f(T x)
// [[likely]] / [[unlikely]]
if (x > 0) [[likely]] { fast_path(); }C++23 additions
cpp
// std::print / std::println
std::println("hello {}", name);
// std::expected
std::expected<int, Error> parse(std::string_view s);
// std::generator (lazy sequences)
std::generator<int> fibonacci();
// std::flat_map / std::flat_set (sorted vectors)
std::flat_map<int, std::string> fm;
// Deducing this (explicit object parameter)
struct Widget {
void f(this Widget& self) { }
auto clone(this auto& self) { return self; }
};
// Monadic optional
opt.and_then(f).transform(g).or_else(h);
// std::ranges::to
auto v = range | std::ranges::to<std::vector>();
// import std (standard library module)
import std;
// std::unreachable
[[noreturn]] void must_not_reach() { std::unreachable(); }