web-dev-qa-db-fra.com

La spécialisation des modèles de fonctions dans std pour les types définis par programme ne sera-t-elle plus autorisée en C ++ 20?

Citation de cppreference.com :

Ajout de spécialisations de modèle

Il est autorisé d'ajouter des spécialisations de modèle pour toute bibliothèque standard | classe (depuis C++ 20) | modèle à l'espace de noms std uniquement si la déclaration dépend de au moins un type défini par programme et la spécialisation satisfait à toutes les exigences du modèle d'origine, sauf lorsque de telles spécialisations sont interdites.

Cela signifie-t-il qu'à partir de C++ 20, l'ajout de spécialisations de modèles de fonction à l'espace de noms std pour les types définis par l'utilisateur ne sera plus autorisé? Si c'est le cas, cela implique que de nombreux morceaux de code existant peuvent se casser, n'est-ce pas? (Il me semble que c'est une sorte de changement "radical".) De plus, il injectera dans de tels codes un comportement indéfini, qui ne déclenchera pas d'erreurs de compilation (les avertissements le seront, espérons-le).

25
Daniel Langr

Dans l'état actuel des choses, il ressemble définitivement à cela. Auparavant, [namespace.std] contenait

Un programme peut ajouter une spécialisation de modèle pour tout modèle de bibliothèque standard à l'espace de noms std uniquement si la déclaration dépend d'un type défini par l'utilisateur et si la spécialisation répond à la norme exigences de la bibliothèque pour le modèle d'origine et n'est pas explicitement interdite.

Alors que le projet actuel indique

Sauf interdiction explicite, un programme peut ajouter une spécialisation de modèle pour tout modèle de classe de bibliothèque standard à l'espace de noms std à condition que (a) la déclaration ajoutée dépend au moins un type défini par le programme et (b) la spécialisation répond aux exigences de la bibliothèque standard pour le modèle d'origine.

mettre l'accent

Et cela ressemble au papier Tu ne spécialiseras pas les modèles de fonction std! de Walter E. Brown en est responsable. Il y détaille un certain nombre de raisons pour lesquelles cela devrait être modifié, comme:

  • Herb Sutter: "les spécialisations ne participent pas à la surcharge. [...] Si vous souhaitez personnaliser un modèle de base de fonction et que cette personnalisation participe à la résolution de surcharge (ou, pour être toujours utilisée en cas de correspondance exacte), faites-en une ancienne fonction, pas une spécialisation. Et, si vous fournissez des surcharges, évitez également de fournir des spécialisations. "
  • David Abrahams: "il est faux d’utiliser la spécialisation des modèles de fonctions [car] il interagit de manière négative avec les surcharges. [...] Par exemple, si vous spécialisez le std::swap pour std::vector<mytype>&, votre spécialisation ne sera pas choisie par rapport au vecteur spécifique de la norme swap, car les spécialisations ne sont pas prises en compte lors de la résolution de surcharge. "
  • Howard Hinnant: "ce problème est réglé depuis longtemps. . . . Ne tenez pas compte des avis/réponses d'experts de Dave dans ce domaine à vos risques et périls. "
  • Eric Niebler: "[à cause de] la manière résolument bizarre que C++ résout les appels de fonction dans les modèles. . . , [nous] faisons un appel sans réserve à swap afin de trouver une surcharge qui pourrait être définie dans [...] les espaces de noms associés [...], et nous faisons using std::swap afin que, au cas où il n'y aurait pas une telle surcharge, nous trouvions la version par défaut définie dans l'espace de noms std. "
  • Norme de codage C++ haute intégrité: "La résolution de surcharge ne prend pas en compte les spécialisations explicites des modèles de fonction. Ce n'est qu'après que la résolution de surcharge aura choisi un modèle de fonction que les spécialisations explicites seront prises en compte. "
24
NathanOliver

Pas vraiment si radical. Ce changement est basé sur cet article de Walter E. Brown . Le papier va dans la logique assez profondément, mais finalement il se résume à ceci:

  1. La spécialisation des modèles de fonction est plutôt médiocre comme point de personnalisation. La surcharge et l'ADL sont bien meilleurs à cet égard. D'autres points de personnalisation sont également abordés dans le document.
  2. La bibliothèque standard ne s'appuie pas trop sur ce mauvais point de personnalisation.
  3. Le changement de libellé mis en place permet en fait d'ajouter des déclarations entières à l'espace de noms std (pas seulement des spécialisations) là où il est explicitement autorisé. Alors maintenant, il y a de meilleurs points de personnalisation .

Étant donné # 1 et # 2, il est peu probable que le code existant se casse. Ou du moins, pas assez pour que ce soit un problème majeur. Le code qui utilisait auto et register a également "cassé" dans le passé, mais cette minuscule quantité de code C++ n'a pas arrêté la progression.

15
StoryTeller