Funktionsüberladung mit Templates
-
Nathan schrieb:
Tja.
Ich finde das schön.^^Solange der Code nur für dich selber ist, ist es ja relativ egal. Wenn du dann aber mal mit mehreren Leuten programmierst, dann sollte man sich an gewisse "Normen" halten. Ansonsten sind die Klasse, usw. nutztlos, weil sie sich einfach nur falsch verhalten. Und wenn du jetzt immer so weiter programmierst, dann wirst du immer wieder in diesen Stil zurückfallen und ihn nur schwer verbessern können...

-
Was spricht gegen
win::message_box::error(e.what());? Da brauchst du dann auch nur noch std::exception zu fangen..
-
OK, das ist ein Argument.
Ich finde aber trotzdem, dass das gut zu meinen Image-Streams und Packet-Streams passen würde...
In welchen Situationen machen Streams/operator << denn wirklich Sinn?
-
Nathan schrieb:
In welchen Situationen machen Streams/operator << denn wirklich Sinn?
Wenn du tatsächlich Stream-Semantik hast. D.h. du kannst mehrere Objekte hintereinander irgendwo reinschieben. Z.B. in ein Packet, das übers Netzwerk versendet wird. Sinnvoll ist dabei, wenn der
operator<<verkettet werden kann, und wenn es möglicherweise auch einenoperator>>mit umgekehrter Semantik gibt.Aber verwende
<<und>>nicht, wenn benannte Funktionen viel aussagekräftiger sind und man erst mal überlegen muss, was der Operator in deinem Kontext bedeuten könnte.
-
Nathan schrieb:
In welchen Situationen machen Streams/operator << denn wirklich Sinn?
Streams=Datenfluss
http://de.wikipedia.org/wiki/Datenstrom
http://en.wikipedia.org/wiki/Stream_%28computing%29<< = formatierte Ausgabe
> = formatierte Eingabe
=> Wenn man einen Datenfluss mit formatiertem Text hat.
Für unformatierte Sachen wie Images oder Packets sind Streambuffer zuständig.
Wobei das alles relativ ist, weil sich die Standardbibliothek nicht einmal selber daran hält. Ist ein riesiger Murks, den man am liebsten umgeht (nicht grundlos haben std::exceptions ein what() und kein operator>>).
-
Für mich ist << = Ausgabe und >> = Eingabe.
Deswegen hatte ich dort den Operator überladen denn Text auf einer Message Box auszugeben ist eine Ausgabe.
Für mich ist der Kontext klar und die Operatoren sind lediglich Alternativen zu benannten Funktionen.
-
Nathan schrieb:
Für mich ist der Kontext klar und die Operatoren sind lediglich Alternativen zu benannten Funktionen.
Es gibt aber einen grossen semantischen Unterschied.
win::message_box::error << "1"; // Erwartung: error enthält "1" win::message_box::error << 2 << '3'; // Erwartung: error enthält "123"win::message_box::error.set_msg("1"); // Erwartung: error enthält "1" win::message_box::error.set_msg("2"); // nur strings erlaubt win::message_box::error.set_msg("3"); // Erwartung: error enthält "3"Wenn du das richtig umsetzen willst, müsste jede Klasse einen stringstream halten und das ist Overkill.
Ausserdem führt dein Ansatz zu Inkonsistenzen
std::deque<int> d; d << 4 << 5 << 6; // ich bin ganz schlau und habe operator>> überladen int a, b; d >> a >> b; // a=4 und b=5 und d.size()=1 d.push_front(3); // leider kein Operator mehr frei int c = d.back(); d.pop(); // ditoDaher: Im Zweifelsfall lieber benannte Funktionen, die haben Namen und jedem ist klar, was sie machen.
-
OK, mein Bild von operator <</operator>> war wohl nicht ganz klar definiert.
Allerdings käme ich nie auf die Idee für deque etc. sie zu überladen, da das für mich keine Aus-/Eingabe ist. Anderseits ist es das schon...
Und eigentlich ist es bei message_box schon so, dass 123 ausgegeben wird, nur in verschiedenen Boxen (Ausgabe ist bei mir ungepuffert, wenn man das so sagen darf).
Trotzdem werde ich hier darauf verzichten.
Wie sieht es mit Bildausgabe aus?main_display << sprite1 << sprite2 << depth_test(false) << rectangle << flush;Ist es da in Ordnung die Operatoren zu verwenden?
-
Ein- und Ausgabe sind sehr weit gefasste Begriffe. Sie sind daher nicht unbedingt ein geeignetes Kriterium für
operator<<undoperator>>.Ich würde zum Zeichnen ebenfalls nicht diese Operatoren verwenden. Was stört dich an
window.draw(sprite1); window.draw(sprite2); window.display();? Hat neben dem besser verständlichen Code auch den Vorteil, dass du mehrere Parameter angeben kannst. Zum Beispiel, wenn du etwas mit einem Shader rendern willst:
window.draw(sprite, shader);
-
Ich weiß es nicht, mir gefällt das optisch nicht so...
Warum gibt es dann bei o/istream die Operatoren? Das ist doch ähnlich wie hier oder irre ich mich da?
-
Nathan schrieb:
Ich weiß es nicht, mir gefällt das optisch nicht so...
Das ist aber die Syntax für Methodenaufrufe, daran solltest du dich in modernen Sprachen besser gewöhnen.
Davon abgesehen:
window.draw(sprite);kannst du lesen als "window draws sprite", expressiver geht gar nicht. Bei<<ist es hingegen ein Rätselraten.
-
...
-
Ich weiß es nicht, ich fand das es schöner aussieht.
Und klar, dass << und >> eigentlich Bitshiftoperatoren sind, ich redete natürlich vom Kontext aus.
Ich werde << und >> nur noch verwenden, wenn der Stream von i/ostream abgeleitet ist/werden kann.
-
Nathan schrieb:
Ich werde << und >> nur noch verwenden, wenn der Stream von i/ostream abgeleitet ist/werden kann.
Es gibt schon auch andere Fälle, wo es sinnvoll sein kann. Aber die Semantik ist üblicherweise sehr ähnlich zu Streams.
Beispiel ist die Klasse
sf::Packetvon SFML. Diese repräsentiert ein Netzwerkpaket, wobei<<und>>Werte ein- und auslesen.
-
Ja, die kenne ich.
Man könnte sie aber auch so implementieren, dass sie von iostream abgeleitet ist.
-
Und wieder einen Abweichler erfolgreich auf Linie gebracht!
Ein voller Erfolg für das Kollektiv!
Ach, kommt schon …optiker schrieb:
Ausserdem führt dein Ansatz zu Inkonsistenzen
Bei Streams gibt es aber keine? Deswegen kann ich auch so toll Binärdaten mittels operator>> einlesen?
Ich habe noch nie die vorparsenden Einlesefunktionen benutzt, denn das haut nur einigermaßen hin, wenn man die Eingabe spezifisch auf sie abstimmt …Nexus schrieb:
Davon abgesehen: window.draw(sprite); kannst du lesen als "window draws sprite"
Ist es nicht eher eine Anweisung, also ein Befehl, keine Aussage? (Vgl.: window, draw sprite)