Search Knowledge

© 2026 LIBREUNI PROJECT

Modern C++ Programming / Modern C++ Features

Structured Bindings and Init Statements

Structured Bindings: Decomposing Objects

C++17 structured bindings provide a concise syntax for unpacking tuples, pairs, arrays, and structs into individual variables.

Basic Syntax

std::pair<int, std::string> get_person() {
    return {42, "Alice"};
}

auto [id, name] = get_person();  // Structured binding
std::cout << id << ": " << name;  // 42: Alice

Binding Pairs and Tuples

std::map<std::string, int> scores = {{"Alice", 95}, {"Bob", 87}};

for (const auto& [name, score] : scores) {
    std::cout << name << ": " << score << '\\n';
}

std::tuple<int, double, std::string> data{42, 3.14, "hello"};
auto [i, d, s] = data;

Binding Arrays

int arr[] = {1, 2, 3};
auto [a, b, c] = arr;  // a=1, b=2, c=3

// Number of bindings must match array size
// auto [x, y] = arr;  // Error: 3 elements, 2 bindings

Binding Structs

Works with any struct/class where all members are public:

struct Point {
    double x, y;
};

Point p{3.0, 4.0};
auto [x, y] = p;  // x=3.0, y=4.0

double distance = std::sqrt(x*x + y*y);

Reference Bindings

std::map<std::string, int> map = {{"key", 42}};

// Reference binding: can modify original
for (auto& [key, value] : map) {
    value *= 2;  // Modifies map
}

// Const reference: read-only
for (const auto& [key, value] : map) {
    std::cout << key << ": " << value << '\\n';
}

Ignoring Values

C++20 allows placeholder with [[maybe_unused]]:

auto [a, [[maybe_unused]] b, c] = std::tuple{1, 2, 3};
// b is not used but no warning

C++26 will support _ as placeholder:

auto [a, _, c] = std::tuple{1, 2, 3};  // C++26

Custom Types

Make custom types decomposable:

class Rectangle {
    double width_, height_;
public:
    Rectangle(double w, double h) : width_(w), height_(h) {}
    
    // Tuple-like interface
    template<size_t I>
    double get() const {
        if constexpr (I == 0) return width_;
        else if constexpr (I == 1) return height_;
    }
};

// Specializations for std::tuple_size and std::tuple_element
namespace std {
    template<>
    struct tuple_size<Rectangle> : integral_constant<size_t, 2> {};
    
    template<size_t I>
    struct tuple_element<I, Rectangle> { using type = double; };
}

Rectangle r{3.0, 4.0};
auto [w, h] = r;  // w=3.0, h=4.0

Init Statements in if and switch (C++17)

Declare and initialize variables in the condition statement with tighter scope.

if with Init Statement

if (auto it = map.find(key); it != map.end()) {
    std::cout << it->second;
    // it is in scope here
}
// it is NOT in scope here

Before C++17:

auto it = map.find(key);  // it pollutes outer scope
if (it != map.end()) {
    std::cout << it->second;
}

switch with Init Statement

switch (auto status = get_status(); status) {
    case Status::OK:
        // use status
        break;
    case Status::ERROR:
        // use status
        break;
}
// status not in scope

Structured Binding in if

Combine init statement with structured binding:

if (auto [iter, inserted] = map.insert({key, value}); inserted) {
    std::cout << "Inserted: " << iter->first << '\\n';
} else {
    std::cout << "Already exists\\n";
}

Range-Based for Init Statement (C++20)

for (auto v = init_value(); auto& elem : container) {
    // v and elem both in scope
    process(v, elem);
}

Use Cases

Lock and Check

if (std::lock_guard lock(mutex); condition()) {
    // Protected section
}
// Lock released

Optional Chaining

if (auto opt = get_optional(); opt.has_value()) {
    std::cout << *opt;
}

Error Handling

if (auto [result, error] = perform_operation(); error) {
    handle_error(error);
} else {
    use_result(result);
}
Conceptual Check

What's the main benefit of init statements in if/switch?

Runtime Environment

Interactive Lab

1#include <iostream>
2#include <map>
3#include <tuple>
4 
5struct Point { double x, y; };
6 
7int main() {
8 // Structured bindings with tuple
9 auto [a, b, c] = std::tuple{1, 2.5, "hello"};
10 std::cout << "Tuple: " << a << ", " << b << ", " << c << '\n';
11
12 // Structured bindings with struct
13 Point p{3.0, 4.0};
14 auto [x, y] = p;
15 std::cout << "Point: (" << x << ", " << y << ")\n";
16
17 // Init statement in if
18 std::map<std::string, int> scores{{"Alice", 95}};
19
20 if (auto it = scores.find("Alice"); it != scores.end()) {
21 std::cout << "Alice's score: " << it->second << '\n';
22 }
23
24 // Structured binding in loop
25 for (const auto& [name, score] : scores) {
26 std::cout << name << " scored " << score << '\n';
27 }
28
29 return 0;
30}
System Console

Waiting for signal...