Benutzerdefinierte Infix-Operatoren

8

Es ist einfach, neue Infix-Operatoren in C ++ einzuführen

%Vor%

Live-Demo

Leider hat dieser Energieoperator eine falsche Priorität und Assoziativität. Meine Frage ist also: Wie behebe ich das? Ich möchte, dass mein <pow> einen höheren Vorrang hat als * und assoziiere mit dem rechten, genau wie in der mathematischen Notation.

Bearbeiten Es ist möglich, den Vorrang zu ändern, indem Sie verschiedene Klammern verwenden, z. |op| , /op/ , *op* oder sogar, wenn man so geneigt ist, <<--op-->> , aber man kann auf diese Weise nicht höher als die höchste Priorität des eingebauten Operators gehen. Aber heute ist C ++ so mächtig mit Template-Metaprogrammierung und Typableitung, dass es einfach einen anderen Weg geben sollte, um das gewünschte Ergebnis zu erreichen.

Außerdem wäre es schön, wenn ich pow und nicht pwr verwenden könnte. Leider bringt #include <cmath> in einigen Implementierungen pow in den globalen Namespace, so dass ein Konflikt entsteht. Können wir operator not so überladen, dass eine Deklaration der Form

erfolgt %Vor%

entfernt std::pow aus dem globalen Namespace?

Weitere Informationen: eine verwandte Website Vorschlag von Bjarne Stroustrup .

    
n.m. 01.04.2016, 12:42
quelle

1 Antwort

6

Das Prinzip der geringsten Überraschung ist wichtig, und es ist der Schlüssel, dass a*b *power* c * d zu a* (b^c) *d auswertet. Zum Glück gibt es eine einfache Lösung.

Um sicherzustellen, dass *power* eine höhere Priorität hat als die Multiplikation, müssen Sie eine ähnliche Technik mit benanntem Operator für die Multiplikation verwenden.

Anstatt die Ergebnisse von *power* und *times* direkt zu berechnen, erstellen Sie stattdessen einen Ausdrucksbaum. Dieser Ausdrucksbaum kann, wenn er ausgewertet wird, beliebige Vorrangregeln anwenden .

Wir können dies mit jedem integrierten Operator tun, was uns eine leicht zu lesende Syntax gibt, die eine Metaprogrammierung der Operatorpräzedenz ermöglicht:

%Vor%

Um zu vermeiden, dass diese Ausdrucksvorlage länger als optimal gespeichert wird, überladen Sie einfach operator auto()&& , um den abgeleiteten Typ zurückzugeben. Wenn Ihr Compiler diese Funktion nicht unterstützt, kann =equals= den richtigen Typ zu geringen Kosten der Übersichtlichkeit zurückgeben.

Beachten Sie, dass die obige Syntax tatsächlich in C ++ unter Verwendung von Techniken ähnlich den OPs realisierbar ist. Eine tatsächliche Implementierung ist größer als ein SO-Post enthalten sollte.

Es gibt noch andere Vorteile. Wie jedermann weiß, sind obskure ASCII-Zeichen in Programmiersprachen in Ungnade gefallen, und Leute, die C ++ lesen, können durch Ausdrücke wie:

verwirrt werden %Vor%

Bei dieser Technik haben alle Operatoren lesbare Namen, die ihre Bedeutung verdeutlichen, und alles wird infix gemacht, anstatt die Infix- und Präfix-Notation zu mischen.

Ähnliche Lösungen, um sicherzustellen, dass pow verfügbar ist, können Sie durch erneutes Implementieren von <cmath> als <cmath_nopow> selbst erledigen. Dadurch wird vermieden, dass der Operator nicht auf Sprachkonstrukte überlädt, was dazu führt, dass sich AST-Grammatik-Monaden entkoppeln und / oder gegen den Standard verstoßen. Vielleicht versuchen Sie Haskell?

    
Yakk 01.04.2016, 14:58
quelle