Xavier Lamorlette

C++ 17

Sommaire :

Syntaxe

Variables inline

Comme pour les fonctions, permet de définir une variable dans plusieurs unités de compilation, avec résolution à l'édition de lien.

Namespaces

namespace A::B::C {
}

Structured binding declarations

std::map<int, std::string> a_map;
auto[iter, succeeded] = a_map.insert(value);
for (const auto & [key, value]: a_map) {
  …
}

Initialisations dans les if et switch

std::map<int, std::string> a_map;
if (auto[iter, succeeded] = a_map.insert(value); succeeded) {
  use_result(iter);
}

Compilation conditionnelle (constexpr if)

template<typename T>
auto Get_value(T t) {
  if (constexpr(std::is_pointer_v<T>)) {
    return * t;
  } else {
    return t;
  }
}

Attribut maybe_unused

voip F([[maybe_unused]] bool a) {
  [[maybe_unused]] bool b = a;
  assert(b);
}

Garantie de l'élision de copie

L'élision de copie pour les valeurs de retour (RVO: Return Value Optimisation) est garantie.

STL

À étudier : Standard Library Utilities in C++.

std::any

std::byte

Pour stocker un octet.

std::optional

std::string_view

Référence non propriétaire et en lecture seule vers une string (std::string ou char *).

std::variant

Type somme : type combinant la somme disjointe des valeurs des différentes parties (comme les unions en C).

std::get_if
std::variant<int, float> int_or_float{12};
if (auto pval = std::get_if<int>(& int_or_float)) {
    std::cout << "value: " << * pval << std::endl;
} else {
    std::cout << "failed" << std::endl;
}
std::holds_alternative
std::variant<int, float> int_or_float{12};
if (std::holds_alternative<int>(int_or_float)) {
    std::cout << "int" << std::endl;
}
std::visit

std::visit est une fonction qui prend en paramètre un visiteur.

Exemple d'utilisation de std::visit avec auto :

using A_or_B = std::variant<A, B>;

std::ostream & operator << (std::ostream & os,
        const A_or_B & a_or_b) {
    std::visit([& os](auto const & element) {
        os << element;
    }, a_or_b);
  return os;
}

Exemple d'utilisation de std::visit avec des surcharges :

struct A_or_B_visitor {
    std::ostream & os;

    A_or_B_visitor(std::ostream & os):
        os(os) {
    }

    void operator () (const A & a) {
        os << "A: " << a;
    }
    void operator () (const B & b) {
        os << "B: " << b;
    }
};

std::ostream & operator << (std::ostream & os,
        const A_or_B & a_or_b) {
    std::visit(A_or_B_visitor(os), a_or_b);
    return os;
}
Overload Pattern
template<typename... T>
struct Overload: T... {
    using T::operator()...;
};
template<class... T>
Overload(T...) -> Overload<...>;

using A_or_B = std::variant<A, B>;
A_or_B a_or_b = A{};

auto Type_of_A_or_B = Overload {
    [](A) {return "A";},
    [](B) {return "B";},
    [](auto) {return "unknown type";}
};

std::cout << std::visit(Type_of_A_or_B, a_or_b) << std::endl;

auto Display_A_or_B = Overload {
    [](const A & a) {
        std::cout << "A: " << a << std::endl;
    },
    [](const B & b) {
        std::cout << "B: " << b << std::endl;
    }
};

std::visit(Display_A_or_B, a_or_b);

En C++20, la ligne template<class... T> Overload(T...) -> Overload<...>; n'est plus nécessaire.

En C++23, on peut vérifier à la compilation que tous les types du variant sont bien pris en charge dans l'overload :

template<typename... T>
struct Overload: T... {
    using T::operator()...;

    consteval void operator()(auto) const {
        static_assert(false, "Unsupported type");
    }
};

Filesystem

Petite sélection :

Choix de la version d'un algorithme de la STL

std::vector<int> v;
std::sort(policy, v.begin(), v.end());

policy:

La dernière mise à jour de cette page date de janvier 2023.

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.