Xavier Lamorlette

C++ 23

Sommaire :

Syntaxe

enum: std::to_underlying

Au lieu de :
enum class Toto: uint8_t {…};
Toto toto {12};
uint8_t value = static_cast<uint8_t>(toto);
Faire :
uint8_t value = std::to_underlying(toto);

Déduction de this

Cela permet de ne plus recourir au Mixin (aussi connu sous le nom de CRTP : “Curiously Recurring Template Pattern”) pour faire du polymorphisme statique.

Au lieu de :

template <typename T>
class Base {
    void interface() {
        static_cast<T *>(this)->implementation();
    }
};

class Derived: Base<Derived> {
    void implementation();
};

On fait, en C++23 :

class Base {
    template <typename Self>
    void interface(this Self && self){
        self.implementation();
    }
};

class Derived: Base {
    void implementation();
};

STL

expected

expected permet de retourner une valeur ou une erreur :

std::expected<int, std::string> foo() {
    if … {
        return 12;
    } else {
        return std::unexpected("error text");
    }
}

auto result = foo();
if (result) {
    std::cout << "value: " << *result << std::endl;
} else {
    std::cout << "error: " << result.error() << std::endl;
}
transform()

transform() appelle une fonction si un expected contient une valeur :

std::expected<int, std::string> ga() {…}

int bu(int) {…}

auto result = ga().transform(bu);
transform_error()

transform_error() appelle une fonction si un expected contient une erreur :

std::expected<int, std::string> ga() {…}

std::string add_error_information(const std::string & error) {
    return std::string("blabla: ") + error;
}

auto result = ga().transform_error(add_error_information);
and_then()

and_then() appelle une fonction si un expected contient une valeur, la fonction appelée retournant elle-même un expected, ce qui permet de chainer des fonctions sans devoir tester si les valeurs intermédiaires sont des erreurs :

std::expected<int, std::string> ga() {…}

std::expected<int, std::string> bu(int) {…}

auto result = ga().and_then(bu);
if (result) {
    std::cout << "value: " << *result << std::endl;
} else {
    std::cout << "error: " << result.error() << std::endl;
}
or_else()

À l'inverse de transform(), or_else() appelle une fonction si un expected contient une erreur :

std::expected<int, std::string> ga() {…}

std::expected<int, std::string> handle_error(const std::string & error) {
    std::cerr << "Error: " << error << std::endl;
    return std::unexpected(error);
}

auto result = ga().or_else(handle_error);

On combine efficacement and_then() et or_else() :

std::expected<int, std::string> ga() {…}

std::expected<int, std::string> bu(int) {…}

std::expected<int, std::string> handle_error(const std::string & error) {
    std::cerr << "Error: " << error << std::endl;
    return std::unexpected(error);
}

auto result = ga().and_then(bu).or_else{handle_error);

Ajouts à optional

Dans std::optional, ajout des méthodes and_then(), or_else() et transform() qui prennent en paramètre une fonction.

Ajout à string

std::string::contains()

mdspan

std::mdspan est un “multidimensional span”.

spanstream

Un std::spanstream est un stream auquel on fournit un span à utiliser :

 char buffer[128] { 0 };
std::span span_buffer(buffer);
std::basic_spanstream span_streanm(span_buffer);
span_streanm << "foo bar";

La dernière mise à jour de cette page date d'août 2024.

Le contenu de ce site est, en tant qu'œuvre originale de l'esprit, protégé par le droit d'auteur.
Pour tout commentaire, vous pouvez m'écrire à xavier.lamorlette@gmail.com.