Approuvé C ++ 20! À quoi s'attendre et quoi préparer pour les développeurs en C ++ 23

L'autre jour à Prague, une réunion du comité international de normalisation C ++ a eu lieu. Et-et-et-et ...



C ++ 20 est prêt! Il reste à mettre un tampon de l'ISO, mais c'est une étape purement formelle avec laquelle il ne devrait pas y avoir de problèmes.

Félicitations à tous pour ce merveilleux événement! Concepts, coroutines, modules, plages, std :: format, constexpr nouveaux et constexpr algorithmes + vecteur + chaîne, datetime, jthread, span, bit_cast et de nombreuses autres petites et grandes innovations.

Ce qu'ils ont réussi à ajouter et à corriger au dernier moment, ce qu'ils ont proposé de casser et ce que tout le monde veut voir en C ++ 23 - à propos de tout cela sous la coupe.

Astuces de C à C ++ 20


Récemment, il y a eu une tradition d'effrayer les développeurs novices avec un comportement non défini (UB) en C ++. Il est temps de le changer!

Ici, par exemple, un tel code est absolument valable pour C:

struct X { int a, b; };

X *make_x() {
  X *p = (X*)malloc(sizeof(struct X));
  p->a = 1;
  p->b = 2;
  return p;
}

Mais en C ++, il y avait de gros problèmes. C fonctionne avec des octets et C ++ fonctionne avec des objets. Mais l'objet a une durée de vie, et avant C ++ 20, le début de vie de l'objet était considéré à partir de l'appel new.

Le comité est très préoccupé par le travail de bas niveau avec les octets et les structures simples. Ils ont adopté des améliorations qui disent qu'un certain ensemble de fonctions (memcpy, memmove, malloc, align_alloc, calloc, realloc, bit_cast) commence la durée de vie de l'objet. Désormais, la plupart des astuces C de bas niveau sont garanties de fonctionner en C ++.

bool est devenu plus fiable en C ++ 20


Devinez quelle est l'erreur:

template <typename T, size_t N>
auto count_unique(const std::array<T, N>& v) {
    return std::unordered_set<T>{v.begin(), v.end()}.size();
}

Réponse
T bool v.begin() v.end() (, libc++ libstdc++) — count_unique 1.

- , std::unordered_set<bool>{v.begin(), v.end()} bool std::unordered_set<bool>{true, true}.

Les transformations dans bool sont maintenant considérées comme des transformations rétrécissantes. Cela nous a permis de trouver des problèmes dans de nombreuses bases de code (plus d'exemples dans la phrase P1957 elle-même ).

Les concepts C ++ 20 accélérés


Jusqu'à récemment, vous pouviez écrire un concept comme celui-ci:

template <class T>
concept Reservable = requires(T v) {
    v.reserve(int{});
};

Et soyez surpris qu'il renvoie des résultats différents:

struct Test;

static_assert(!Reservable<Test>);

struct Test {
    void reserve(int);
};

static_assert(Reservable<Test>);

La dernière fois, nous avons envoyé un commentaire du pays: «Rendre impossible l'utilisation de caractères incomplets dans les concepts, sinon vous obtenez plusieurs violations ODR». Notre commentaire a été rejeté, mais nous avons obtenu en partie le résultat souhaité maintenant avec la proposition P2104.

En prime, nous obtenons une compilation plus rapide, car les compilateurs ont désormais le droit de mettre en cache les résultats de l'application des concepts aux types.

Modifications mineures en C ++ 20


  • Les plages ont obtenu la méthode ssize.
  • La liaison interne d'entité n'est plus visible lors de l'instanciation d'entités de liaison de module (le compilateur vous dira ce qui ne va pas au stade de la compilation).
  • Nous avons tordu les règles des modules afin qu'il soit plus facile pour n'importe quel outil de travailler avec eux.

Et cassons tout en C ++ 23 ou C ++ 26?


Un débat prolongé a déclenché une proposition pour une interface d'application binaire (ABI, ne pas confondre avec l'API). Des questions intéressantes ont été soulevées:

1. Nous pouvons complètement changer ABI en C ++ 23 et obtenir un gain de performances de 5 à 10%.


De plus, toutes les anciennes bibliothèques C ++ devront être reconstruites; elles ne pourront pas se lier aux bibliothèques avec la nouvelle ABI. Vous ne pouvez pas utiliser des bibliothèques créées par des versions antérieures de C ++ dans un projet C ++ 23.

Eh bien, bien sûr, il y aura toujours de vieux logiciels commerciaux que personne ne réassemblera, mais qui feront glisser sa bibliothèque standard (oui, les jeux vidéo, je parle de vous!).

Avec une légère marge de vote, ABI a décidé de ne pas casser en C ++ 23.

2. Donnons aux utilisateurs la garantie que nous essaierons de ne pas casser / modifier l'ABI.


Et puis ils ont décidé de ne pas donner de garantie. Différents fournisseurs ont des plans différents pour leurs plates-formes, et parfois ils peuvent se permettre de casser l'ABI, souvent sans nuire aux utilisateurs.

Et ajoutons partout, sauf?


Historiquement, dans les fonctions standard avec des conditions préalables ne sont pas marquées comme noexcept, même si elles ne lèvent jamais d'exceptions. Ici, par exemple, operator -> have std :: optional:

constexpr const T* operator->() const;
constexpr T* operator->();
    Requires: *this contains a value.
    Returns: val.
    Throws: Nothing.

Il ne jette rien, mais au lieu de non, sauf qu'il dit en mots que "jette: rien", car il y a une condition préalable "* cela contient une valeur".

Les utilisateurs sans noex seront plus clairs. Une bonne idée en P1656 !



Non!

Il existe tout un sous-groupe SG21: Contrats, qui propose un mécanisme commun de contrôle des contrats (pré- et post-conditions). Les gestionnaires de contrats peuvent lever une exception, si une exception est levée à partir de la fonction noexcept, elle sera std :: terminate et l'application se bloquera. Si vous insérez une béquille spéciale qui, pour les contrats, les exceptions peuvent sortir d'une fonction noexcept ... alors tout tombe en panne de toute façon, les traits de type sont guidés par la présence de noexcept, et ils commencent à vous mentir, une fonction marquée noexcept avec une condition préalable lèvera une exception.

Mais ce n'est pas le plus gros problème. Il existe des fourches de bibliothèques standard qui, déjà dans certains cas, insèrent déjà explicitement des vérifications de précondition. Par exemple, avez-vous un projet critique dont la disponibilité doit être maximisée. Vous utilisez un fork similaire, et si quelqu'un a soudainement appelé std :: vector :: back () pour un vecteur vide, une exception est levée, qui est traitée plus haut dans le code et le repli commence à être utilisé. Avec les modifications de P1656, une telle bibliothèque ne peut plus être considérée comme standard.

Et ce ne sont pas tous les problèmes! .. Non seulement le noex supplémentaire pour la bibliothèque standard apportera-t-il des effets positifs sous la forme d'une diminution de la taille des fichiers binaires ou de plus de performances, non seulement le changement brisera le code d'au moins deux sociétés, non seulement il détruira l'une des façons utilisation de contrats ... ainsi la proposition a également été approuvée en deux sous-groupes.

Les mérites de RG21


Comme toujours, nous avons travaillé dans différents sous-groupes, partagé notre expérience de mise en œuvre, présenté des propositions dont les auteurs ne pouvaient pas venir.

L'une des idées exceptionnelles que nous avons eu la chance de présenter était l'idée d'Anton Zhilin P2025 Élision de copie garantie pour les objets de retour nommés . Son implémentation permettra de créer des fonctions d'usine pour les objets sans copier et déplacer les constructeurs. En fait, il s'agit d'un mouvement destructeur, qui existe secrètement dans la norme depuis le milieu des années 90 et qui était spécifiquement interdit par les règles linguistiques individuelles.

Nous avons réussi à faire glisser l'idée à travers les instances EWG-I et EWG grâce à l'excellente élaboration de l'idée par l'auteur lui-même. L'étape du CWG est restée, et après quelques réunions, il y a toutes les chances de voir les mots nécessaires dans la norme et les premières implémentations dans les compilateurs.

En plus de cette idée, nous avons fait glisser l'idée de P1990R0: Ajouter l'opérateur [] à std :: initializer_list via LEWG-I, nous avons obtenu un retour utile sur P1944R0: constexpr <cstring> et <cwchar> . Les deux idées de Daniil Goncharov ont toutes les chances d'être en C ++ 23.

Dans le domaine de std :: hash, un échec inattendu nous attendait. La discussion de p1406r1: Ajouter plus de spécialisations std :: hash s'est soudainement transformée en une discussion sur les cas limites dégénérés et les possibilités du C ++ 2 * distant. En conséquence, le comité a décidé de ne rien changer.

Avec SG6 et Numbers n'a pas grandi ensemble. Les principales discussions de SG6 se sont croisées avec celles d'ABI, c'est pourquoi le quorum de SG6 ne s'est pas accumulé. À cause de cela p1889: Travail numérique C ++ en cours , P2010: Supprimez les opérateurs iostream de P1889 etP1890: Les problèmes de travail numérique en cours de C ++ n'ont pas été discutés.

Plans C ++ 23


Depuis le début du développement de C ++ 20, le comité a commencé à agir comme prévu. À savoir, identifier plusieurs idées principales intéressantes pour la prochaine norme, après quoi, lors de toutes les réunions ultérieures, ne pas examiner les propositions sur d'autres sujets, sinon toutes ont été discutées sur le principal.

Pour C ++ 23, un tel plan vient d'être approuvé à Prague. Les principales priorités du C ++ 23:

  1. Prise en charge de Corutin dans la bibliothèque standard
  2. Convertir une bibliothèque standard en modules
  3. Exécuteurs
  4. La mise en réseau

Dans le premier paragraphe, tout le monde sera guidé par la bibliothèque CppCoro . Donc, si vous voulez déjà utiliser des coroutines C ++ 20, vous devez commencer par utiliser cette bibliothèque.

Avec les modules, deuxième point, il suffit de s'asseoir et de le faire, aucune difficulté particulière n'est à prévoir.

Mais les exécuteurs sont un problème. Leur conception n'est pas évidente, tous les cas d'utilisation ne sont pas couverts, dans leur forme actuelle, ils n'ont été utilisés par personne, et la conception n'est toujours pas approuvée.

Le comité est également convenu de prioriser les propositions dans les domaines suivants:

  • Réflexion
  • Correspondance de motifs
  • Contrats

Au lieu de totaux


C ++ 20 est prêt, il est temps de travailler sur C ++ 23! La prochaine réunion du Comité aura lieu en été, donc si vous avez une idée décente de la nouvelle norme - partagez-les sur stdcpp.ru et Telegram-chatter ProCxx .

Eh bien, tous ceux qui veulent discuter avec des représentants du comité en direct - regardez les réunions et les conférences C ++ *:


* Life hack: vous n'êtes pas obligé de payer un billet de conférence si vous êtes conférencier.

All Articles