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).
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
pourstd::vector<mytype>&
, votre spécialisation ne sera pas choisie par rapport au vecteur spécifique de la normeswap
, 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 faisonsusing 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. "
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:
É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.