Pourquoi std :: rel_ops :: operator sera-t-il déconseillé en C ++ 20?

Selon cppreference.com , std::rel_ops::operator!=,>,= obsolète en C ++ 20.

Quelle est la raison derrière?

    En C ++ 20, vous obtenez une comparaison à trois voies (opérateur <=> ), qui “génère” automatiquement des comparaisons par défaut si elles sont fournies:

     struct A { // You only need to implement a single operator. std::strong_ordering operator<=>(const A&) const; }; // Comstackr generates all 6 relational operators A to1, to2; if (to1 == to2) { /* ... */ } // ok if (to1 <= to2) { /* ... */ } // ok, single call to <=> 

    La comparaison à trois voies std::rel_ops nombreux avantages par rapport à std::rel_ops , ce qui explique probablement pourquoi les opérateurs std::rel_ops sont obsolètes. Sur le dessus de ma tête:

    • Il est plus polyvalent puisque, selon le type de retour d’ operator<=> ( std::strong_ordering , std::weak_ordering , …), seuls les opérateurs pertinents sont générés. Voir l’en-tête pour plus d’informations.

    • Vous n’apportez pas un tas de surcharges d’opérateurs using namespace std::rel_ops un modèle en using namespace std::rel_ops .

    • Vous pouvez demander au compilateur de générer pour vous l’opérateur à trois voies en le configurant par défaut ( auto operator<=>(A const&) = default ) – Ceci générera essentiellement une comparaison lexicographique des classes de base et des membres de données non statiques, en plus déduira le bon type de commande si le type de retour est auto .

    Quelle est la raison derrière?

    rel_ops est déconseillé par le support de la bibliothèque pour l’opérateur Spaceship (Comparison) . Le papier ne liste aucune motivation, mais il apparaît dans le papier du vaisseau spatial :

    Cela englobe l’espace de noms std::rel_ops , nous proposons donc également de supprimer (ou de std::rel_ops obsolète) std::rel_ops .

    Il y a quatre raisons mentionnées dans le document (y compris la correction et la performance). Mais un gros std::rel_ops qui n’est pas mentionné dans les deux documents est que std::rel_ops ne std::rel_ops tout simplement pas. La règle de base est que les opérateurs sont trouvés en utilisant ADL. rel_ops ne vous donne pas les opérateurs ADL-trouvables, il déclare simplement les modèles de fonctions non contraintes comme:

     namespace std { namespace rel_ops { template< class T > bool operator!=( const T& lhs, const T& rhs ) { return !(lhs == rhs); } } } 

    Donc, en utilisant des algorithmes comme:

     struct X { ... }; bool operator<(X const&, X const&) { ... }; std::sort(values.begin(), values.end(), std::greater<>{}); 

    Cela ne fonctionne tout simplement pas, sauf si vous vous assurez de:

     #include  using namespace std::rel_ops; 

    De manière assez homogène partout où vous en êtes le premier à inclure pour vous assurer que ces opérateurs sont visibles au moment de la définition de chaque modèle de fonction que vous pouvez éventuellement appeler.

    Donc, l’ operator<=> est simplement ssortingctement supérieur:

    • Cela fonctionne réellement.
    • Vous devez seulement écrire une fonction ( <=> ) au lieu de deux ( == et < )
    • En règle générale, vous devez écrire zéro fonction ( = default )
    • Ai-je mentionné que cela fonctionne réellement?

    C ++ 20 fournit une comparaison à trois voies , si bien que les uniques deviennent obsolètes.