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);
}

Type sous-jacent pour les enum

enum class Toto: uint32_t {
  First = 0
};
Toto toto {12};

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 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.