67 votes

Optimisation de la loi de Morgan avec opérateurs surchargés

Tout programmeur devrait le savoir :

De Morgan 1
De Morgan 2
( Les lois de Morgan)

Dans certaines circonstances, afin d'optimiser le programme, il peut arriver que le compilateur modifie (!p && !q) a (!(p || q)) .

Les deux expressions sont équivalentes, et cela ne fait aucune différence d'évaluer la première ou la seconde.
Mais en C++, il est possible de surcharger les opérateurs, et l'opérateur surchargé ne respecte pas toujours cette propriété. Donc, transformer le code de cette façon va en fait modifier le code.

Le compilateur doit-il utiliser les lois de De Morgan lorsque ! , || y && sont surchargés ?

79voto

sergej Points 1749

Notez que :

Les opérateurs intégrés && et || effectuent une évaluation des courts-circuits. (ne pas évaluer le second opérande si le résultat est connu après évaluation du premier), mais les opérateurs surchargés se comportent comme des appels de fonction ordinaires y toujours évaluer les deux opérandes .

... Parce que les propriétés de court-circuitage de l'opérateur&& et de l'opérateur|| ne s'appliquent pas aux surcharges, et parce que les types à sémantique booléenne sont peu courants, seules deux classes de la bibliothèque standard surchargent ces opérateurs ...

Fuente: http://en.cppreference.com/w/cpp/language/operator_logical (c'est moi qui souligne)

Et ça :

S'il existe un candidat écrit par l'utilisateur avec le même nom et les mêmes types de paramètres qu'une fonction d'opérateur candidate intégrée, l'option la fonction d'opérateur intégré est cachée et ne fait pas partie de l'ensemble des fonctions candidates.

Source : n4431 13.6 Opérateurs intégrés [over.built] (c'est moi qui souligne)

En résumé, les opérateurs surchargés se comportent comme des fonctions ordinaires, écrites par l'utilisateur.

NON, le compilateur ne remplacera pas un appel d'une fonction écrite par l'utilisateur par un appel d'une autre fonction écrite par l'utilisateur. Agir autrement serait potentiellement une violation de la "comme si" règle.

18voto

Petr Points 4434

Je pense que vous avez répondu à votre propre question : non, un compilateur ne peut pas faire cela. Non seulement les opérateurs peuvent être surchargés, mais certains ne peuvent même pas être définis. Par exemple, vous pouvez avoir operator && y operator ! définis, et operator || pas du tout défini.

Notez qu'il existe de nombreuses autres lois que le compilateur ne peut pas suivre. Par exemple, il ne peut pas modifier p||q a q||p ainsi que x+y a y+x .

(Tout ce qui précède s'applique aux opérateurs surchargés, puisque c'est ce que la question demande).

9voto

hvd Points 42125

Non, dans ce cas, la transformation serait invalide. L'autorisation de transformer !p && !q en !(p || q) est implicite, par la règle du as-if. La règle as-if permet toute transformation qui, grosso modo, ne peut être observée par un programme correct. Lorsque des opérateurs surchargés sont utilisés et permettraient de détecter la transformation, cela signifie automatiquement que la transformation n'est plus autorisée.

5voto

Matteo Italia Points 53117

Opérateurs surchargés en soi ne sont que du sucre syntaxique pour les appels de fonctions le compilateur lui-même n'est pas autorisé à faire des suppositions sur les propriétés qui peuvent ou non exister pour de tels appels. Les optimisations qui exploitent les propriétés d'un opérateur spécifique (par exemple, les propriétés de De Morgan pour les opérateurs booléens, la commutativité pour les sommes, la distributivité pour la somme/le produit, la transformation de la division intégrale en une multiplication appropriée, ...) ne peuvent être employées que lorsque les "opérateurs réels" sont utilisés.

Remarquez plutôt que certaines parties du bibliothèque standard peut associer une signification sémantique spécifique aux opérateurs surchargés - par exemple, std::sort s'attend par défaut à un operator< qui respecte un ordre faible et strict entre les éléments - mais cela est bien sûr indiqué dans les conditions préalables de chaque algorithme/conteneur.

(incidemment, la surcharge && y || devraient probablement être évités de toute façon car ils perdent leurs propriétés de court-circuitage lorsqu'ils sont surchargés, leur comportement devient alors surprenant et donc potentiellement dangereux)

4voto

Vous demandez si le compilateur peut arbitrairement réécrire votre programme pour faire quelque chose que vous n'avez pas écrit.

La réponse est : Bien sûr que non !

  • Là où les lois de De Morgan s'appliquent, elles peuvent être appliquées.
  • S'ils ne le font pas, ils peuvent ne pas le faire.

C'est vraiment aussi simple que cela.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X