operator-> in Templateklasse überladen
-
Probiere mal
bool NonsenseCondition(Test<int> *w1) { return ((*w1)->me==this->me?1:0); }(sofern w1 nicht null ist)
-
Was versprichst du dir eigentlich von deinem überladenen operator->? Eine sinnvolle Anwendung ist Objekte die eigentlich keine Pointer sind, so aussehen zu lassen als wären es welche, wie z.B. iterators oder smart pointer. In dem Fall ist das was operator-> liefert unterschiedlich von einem Pointer auf das Objekt. Wenn es beides das gleiche ist, wie in deinem Beispiel, ist der einzige Vorteil, dass man statt obj.somefunc() auch obj->somefunc() schreiben kann. Und wenn man zwei Möglichkeiten hat das Gleiche zu schreiben sorgt das nur wieder für Inkonsistenz.
-
marius.schmidt schrieb:
Obj ist ein Pointer auf meine Templateklasse. Um genau zu sein "Test<int>*".
Was bedeutet das denn dann, wie müsste der Aufruf verändert werden, damit die Überladung passt, oder umgekehrt?Wenn
Objein "eingebauter" Zeiger ist, dann wird natürlich auch die eingebaute->Logik verwendet (man könnte sagen: der eingebauteoperator ->-- wobei der Standard das IIRC nicht so nennt). D.h. der Zeiger wird ganz normal dereferenziert. Das Ergebnis davon ist dann eine Referenz, und damit ist der Vorgang abgeschlossen.
Auf diese Referenz wird dannNonsenseConditionaufgerufen.Wenn du willst dass dein
operator ->aufgerufen wird, dann musst du mit einer Referenz starten.
D.h. wennObjhier wieder ein "eingebauter" Zeiger ist, und du möchtest dass 2x deinoperator ->aufgerufen wird, dann müsstest du(*Obj)->NonsenseCondition((*Obj)->GiveMeMe());schreiben.
-
@sebi707
Ich glaube (hoffe) nicht dass es ihm um eine sinnvolle Anwendung geht, sondern nur darum zu verstehen wieoperator ->Überladung in C++ funktioniert.
-
Da glaubst (hoffst) du genau richtig.
Es geht, um genau zu sein, um das Testen einer von uns eingesetzten Implementierung eines Iterators.
Ich bin also nicht der, der das schreiben muss, sondern der der gucken muss ob alles aufgerufen wird ... Und das wird operator-> leider nicht ...Ich habe jetzt mal den Vorschlag von hustbaer genommen:
Test<T> *me; (*w1)->me; (*w1)->GiveMeMe(); (*w1)->NonsenseCondition();Das Ende vom Lied ist die folgende Fehlermeldung:
loop in sequence of "operator->" functions starting at class "Test<int>"
Für alle 3 Aufrufe ...
Ich glaube somit kann ich behaupten, dass der Aufruf nun zumindest versucht wird. Nur funktionieren will es eben immer noch nicht.Ist denn vielleicht grundsätzlich der Gedanke falsch, dass der operator-> ein Objekt der eigenen Klasse zurückgeben kann?
Wie gesagt: In den Erklärungen bei Google war komischer Weise meist ein anderer Rückgabetyp in Verwendung.Beim rumprobieren ist mir außerdem noch aufgefallen, dass *(w1).me funktionieren würde. Ich hätte aber eher damit gerechnet, dass *(w1)->me und w1.me im Endeffekt (ohne eine Überladung) das Gleiche wären. Ist dem nicht so?
Lg
-
marius.schmidt schrieb:
Ist denn vielleicht grundsätzlich der Gedanke falsch, dass der operator-> ein Objekt der eigenen Klasse zurückgeben kann?
Der operator-> ist ein wenig eigenartig. Wie du daran erkennen kannst, dass er keine Parameter hat, ist er sozusagen unär. Wenn du a->b schreibst, und für a ist operator-> überladen, dann wird b zunächst gar nicht angefasst. Es wird ausgewertet, was a.operator->() zurückgibt, und damit wird dann wieder ->b ausgewertet:
(a.operator->())->b
Wenn der operator-> also ein Objekt einer Klasse zurückgibt, die wiederum operator-> überlädt, dann wird danach eben dieser Operator aufgerufen. Das geht so lange weiter, bis irgendwann ein operator-> einen "echten" Zeiger zurückgibt.
Da der operator-> deiner Klasse das Objekt selbst zurückgibt, terminiert das nicht.
-
marius.schmidt schrieb:
Ist denn vielleicht grundsätzlich der Gedanke falsch, dass der operator-> ein Objekt der eigenen Klasse zurückgeben kann?
Sieht so aus.
marius.schmidt schrieb:
In den Erklärungen bei Google war komischer Weise meist ein anderer Rückgabetyp in Verwendung.
Wieso "komischer Weise"? WTF? Es ist total normal nen anderen Typ zurückzugeben, was hier komisch bzw. eher schon total beknackt ist, ist dein Versuch operator -> nen Zeiger auf den eigenen Typ zurückgeben zu lassen.
-
Was daran beknackt sein soll, weiß ich zwar nicht. Aber naja ...
Darin lag ganz einfach nur mein Mißverständnis, wenn ich das so richtig verstehe.
Ich hatte ganz einfach nur das Gefühl dass aus einem *(w1)->me ein w1.me wird. In dem Fall hätte mein Gedanke hinter dem Beispiel gepasst.
Zumal ja der Compiler nicht gemeckert hat. Bei einfacheren Operatoren kommt bei einem falschen Datentyp eine Meldung.Ich denke aber zumindest, dass ich dann jetzt so ungefähr das Problem verstanden habe. Danke für die Hilfe.
-
hustbaer schrieb:
was hier komisch bzw. eher schon total beknackt ist, ist dein Versuch operator -> nen Zeiger auf den eigenen Typ zurückgeben zu lassen.
Neuerdings kann man ja Funktionen auch so deklarieren
auto foo(T param) -> result;Leider hat das Standardkomittee vergessen, auch den Funktionsaufruf zu verbessern.
Zum Glück gibt es dafür eine Lösung#include <utility> #include <iostream> int old_fak(int n) { return n ? n * old_fak( n - 1 ) : 1; } struct new_fak { int input; struct res { const int&& value; const res* operator->() const { return this; } }; const res operator->() const { return { input ? input * new_fak{ input - 1 }->value : 1 }; } }; int main() { std::cout << old_fak(4) /* old-style */ << '\n'; std::cout << new_fak{5}->value /* modern */<< '\n'; }
-
marius.schmidt schrieb:
Es geht, um genau zu sein, um das Testen einer von uns eingesetzten Implementierung eines Iterators.
Ich bin also nicht der, der das schreiben muss, sondern der der gucken muss ob alles aufgerufen wird ... Und das wird operator-> leider nicht ...Vielleicht solltet ihr eure Iterator Implementierung so umstellen, dass ihr keinen Pointer auf den Iterator habt sondern wirklich das Objekt selbst oder maximal eine Referenz darauf, wenn es teuer ist den Iterator zu kopieren. Dann kannst du dir die ganzen (*obj)-> Geschichten sparen und direkt obj-> schreiben.
-
@camper

Seit wann lässt du dich denn dazu hinreissen Scherze zu machen?