Skip to content
C++

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(); }
Edit on GitHub