Mastering Modern C++: Essential Features in C++17 and C++20

Mastering Modern C++: Essential Features in C++17 and C++20
8 minutes

Feb 15, 2024

Stay in the loop

Join thousands of readers and get the best content delivered directly to your inbox.

Get a list of personally curated and freely accessible ML, NLP, and computer vision resources for FREE on newsletter sign-up.

As a robotics engineer deeply entrenched in C++ development, staying up-to-date with the latest language features is crucial. The C++17 and C++20 standards have introduced a wealth of new features that can significantly enhance our code's readability, efficiency, and safety. In this post, we'll explore some of the most impactful additions and how they can be applied in robotics software development.

C++17 Features

1. Structured Bindings

Structured bindings allow us to unpack multiple values from tuples, arrays, or structs into separate variables.

std::tuple<double, double, double> get_position();

auto [x, y, z] = get_position();
// Now x, y, and z are separate variables

This is particularly useful when dealing with sensor data or coordinate systems in robotics applications.

2. if and switch with Initializers

We can now include an initializer in if and switch statements, limiting the scope of variables and making our code cleaner.

if (auto sensor_data = read_sensor(); sensor_data.is_valid()) {
    process_data(sensor_data);
}
// sensor_data is not accessible here

3. std::optional

std::optional provides a safer way to handle values that may or may not exist, which is common in sensor readings or algorithm results.

std::optional<double> get_distance_to_obstacle();

if (auto distance = get_distance_to_obstacle(); distance.has_value()) {
    adjust_speed(*distance);
} else {
    proceed_with_caution();
}

C++20 Features

1. Concepts

Concepts allow us to specify constraints on template parameters, making template code more readable and providing better error messages.

template<typename T>
concept Sensor = requires(T s) {
    { s.read() } -> std::same_as<double>;
    { s.is_calibrated() } -> std::same_as<bool>;
};

template<Sensor S>
void process_sensor_data(S& sensor) {
    if (sensor.is_calibrated()) {
        auto reading = sensor.read();
        // Process the reading
    }
}

2. Ranges

The Ranges library provides a more intuitive way to work with sequences of data, which is particularly useful for processing streams of sensor data or controlling multiple actuators.

std::vector<double> sensor_readings = get_sensor_readings();
auto filtered_readings = sensor_readings 
    | std::views::filter([](double r) { return r > 0; })
    | std::views::transform([](double r) { return r * 2; });

3. Coroutines

Coroutines enable more natural expression of asynchronous and concurrent code, which is essential in robotics for handling multiple tasks and sensor inputs simultaneously.

task<void> robot_routine() {
    while (true) {
        auto sensor_data = co_await read_sensors();
        auto plan = co_await compute_path(sensor_data);
        co_await execute_movement(plan);
    }
}

4. constexpr Improvements

C++20 significantly expands what can be done in constexpr contexts, allowing more computations to be performed at compile-time. This can be particularly useful for optimizing robotics algorithms.

constexpr double PI = 3.14159265358979323846;

constexpr double degrees_to_radians(double degrees) {
    return degrees * PI / 180.0;
}

// This will be computed at compile-time
constexpr double right_angle_in_radians = degrees_to_radians(90.0);

Conclusion

These new features in C++17 and C++20 offer powerful tools for robotics developers. Structured bindings and initializer statements help us write cleaner, more expressive code. std::optional improves our handling of uncertain data. Concepts make our templates more robust and self-documenting. Ranges simplify data processing pipelines, while coroutines offer new ways to manage complex, asynchronous robot behaviors.

As we continue to push the boundaries of what's possible in robotics, leveraging these modern C++ features will be key to writing more efficient, readable, and maintainable code. The next time you're working on a robotics project, consider how these features might help you create better solutions.

Remember, mastering these features takes practice. Don't hesitate to experiment and refactor existing code to take advantage of what modern C++ has to offer. Happy coding!

Authors

Federico Sarrocco

Federico Sarrocco

View Portfolio