Skip to content

Modern Utilities (C++17)

C++17 introduced several vocabulary types and utilities that make code safer and more expressive, reducing the need for custom error handling or complex type hierarchies.

std::optional (Maybe a Value)

std::optional<T> represents a value that may or may not be present. It is a safer alternative to returning pointers (which can be null) or magic values (like -1).

#include <optional>

std::optional<int> parse_int(const std::string& str) {
    if (is_valid_number(str)) {
        return std::stoi(str);
    }
    return std::nullopt; // No value
}

auto result = parse_int("123");
if (result) { // Check if value exists
    std::cout << "Value: " << *result; // Access value
} else {
    std::cout << "Invalid number";
}

// Use default value if empty
int value = result.value_or(0); 

std::variant (Type-Safe Union)

std::variant<T, U, ...> can hold a value of one of the specified types. It is a type-safe replacement for C-style union.

#include <variant>

std::variant<int, float, std::string> data;

data = 10;
data = 3.14f;
data = "Hello";

// Accessing values
if (std::holds_alternative<std::string>(data)) {
    std::cout << std::get<std::string>(data);
}

// Visiting (Pattern Matching)
std::visit([](auto&& arg) {
    std::cout << arg;
}, data);

std::any (Type Erasure)

std::any can hold a value of any copyable type. It is more flexible than variant but less efficient and requires any_cast to retrieve the value.

#include <any>

std::any a = 1;
a = std::string("Hello");

try {
    std::string s = std::any_cast<std::string>(a);
} catch (const std::bad_any_cast& e) {
    std::cout << e.what();
}

Structured Binding

Structured binding allows you to unpack tuples, pairs, structs, and arrays into individual variables.

std::pair<int, int> get_coordinates() {
    return {10, 20};
}

auto [x, y] = get_coordinates();
std::cout << x << ", " << y;

// Iterating over a map
std::map<std::string, int> scores;
for (const auto& [name, score] : scores) {
    std::cout << name << ": " << score << "\n";
}

Filesystem Library (std::filesystem)

The <filesystem> library provides a portable way to interact with the file system.

#include <filesystem>
namespace fs = std::filesystem;

void list_files(const fs::path& dir_path) {
    if (fs::exists(dir_path) && fs::is_directory(dir_path)) {
        for (const auto& entry : fs::directory_iterator(dir_path)) {
            std::cout << entry.path().filename() << "\n";
        }
    }
}

// Creating directories
fs::create_directory("logs");

// Copying files
fs::copy_file("config.txt", "config.bak", fs::copy_options::overwrite_existing);