Modern C++ Features: ranges, optional, variant and format

Modern C++ is much easier and safer than the old style. These are the features to know.

std::optional: a value which may be missing

#include <iostream>
#include <optional>
#include <string>

std::optional<int> find_age(const std::string& name) {
    if (name == "Riya") return 21;
    return std::nullopt;
}

int main() {
    if (auto age = find_age("Riya")) std::cout << "Age " << *age << '\n';
    std::cout << find_age("Aman").value_or(-1) << '\n';
}
Output

Age 21
-1

std::variant: one of many types

#include <iostream>
#include <string>
#include <variant>

int main() {
    std::variant<int, double, std::string> v = 42;
    v = std::string("hello");

    std::visit([](const auto& x) { std::cout << x << '\n'; }, v);
    std::cout << v.index() << ' ' << std::holds_alternative<std::string>(v) << '\n';
}
Output

hello
2 1

Ranges and views (C++20)

Ranges let you chain steps on a container, like a pipeline. Views are lazy: the work is done only when you read the result.

#include <algorithm>
#include <iostream>
#include <ranges>
#include <vector>

int main() {
    std::vector<int> numbers = {5, 12, 8, 3, 20, 15, 10};

    auto result = numbers
        | std::views::filter([](int n) { return n > 7; })
        | std::views::transform([](int n) { return n * 2; });

    for (int x : result) std::cout << x << ' ';
    std::cout << '\n';

    for (int i : std::views::iota(1, 6)) std::cout << i << ' ';
    std::cout << '\n';
    std::cout << std::ranges::count(numbers, 3) << '\n';
}
Output

24 16 40 30 20
1 2 3 4 5
1

std::format and std::print

#include <format>
#include <iostream>
#include <print>

int main() {
    std::string s = std::format("{} is {} years old, score {:.1f}", "Riya", 21, 88.456);
    std::cout << s << '\n';
    std::println("{:>6} | {:<6} | {:^6}", "a", "b", "c");
}
Output

Riya is 21 years old, score 88.5
a | b | c

Structured bindings, if with init, string_view

#include <iostream>
#include <map>
#include <string>

int main() {
    std::map<std::string, int> stock{{"pen", 40}, {"book", 15}};
    for (const auto& [item, qty] : stock) {
        std::cout << item << '=' << qty << ' ';
    }
    std::cout << '\n';

    if (auto it = stock.find("pen"); it != stock.end()) {
        std::cout << "pen found: " << it->second << '\n';
    }
}
Output

book=15 pen=40
pen found: 40

Other useful things

  • constexpr and consteval: do work at compile time.
  • std::span (C++20): a view of a contiguous range, like an array or a vector.
  • [[nodiscard]], [[maybe_unused]]: attributes which help the compiler.
  • Modules (C++20) and coroutines (C++20): bigger features, still being adopted.
#include <iostream>
#include <span>
#include <vector>

int sum(std::span<const int> values) {
    int total = 0;
    for (int v : values) total += v;
    return total;
}

int main() {
    std::vector<int> v = {1, 2, 3, 4};
    int a[3] = {10, 20, 30};
    std::cout << sum(v) << ' ' << sum(a) << '\n';        // one function for both
}
Output

10 60

Note: Use the newest standard your compiler and team can use. Next: C++ Multithreading.

Congratulations! Chapter Finished. Learn more about the similar topics:
Exercises & Assignments
No Content Found.
Interview Questions & Answers
No Content Found.