nichtkonstanter rückgabewert direkt verwenden
-
misst die Leerzeichen wurden verschluckt...Tut mir Für Dreifachpost leid habe erst jetzt den Vorschaubutton entdeckt ;P
Naja so könnte die Baumstruktur aussehen:
---------------E+F
---------------\-/
------------D+0
-------------\-/
----------C+0
----------\-/
-----------0
A+B-----/
-\|-----/
--0---/
---\-/
----0LG Schnupfbear
ps gibt es kein Edit-Button?
-
Schnupfbear schrieb:
misst die Leerzeichen wurden verschluckt...
Verwende Code-Tags

Schnupfbear schrieb:
ps gibt es kein Edit-Button?
Wenn du registriert bist schon. Man kann die einzelnen Unregistrierten nicht unterscheiden, daher auch keine Edit-Möglichkeiten anbieten.
Und was ist deine Frage?

Deine Wrapper-Klasse ist nicht kopierbar, falls dies das Problem ist, weil du darin Referenzen als Member verwendest.Grüssli
-
Dravere schrieb:
Schnupfbear schrieb:
misst die Leerzeichen wurden verschluckt...
Verwende Code-Tags

Schnupfbear schrieb:
ps gibt es kein Edit-Button?
Wenn du registriert bist schon. Man kann die einzelnen Unregistrierten nicht unterscheiden, daher auch keine Edit-Möglichkeiten anbieten.
Und was ist deine Frage?

Deine Wrapper-Klasse ist nicht kopierbar, falls dies das Problem ist, weil du darin Referenzen als Member verwendest.Grüssli
Und gibt es kein Workaround damit das Wrapperobjekt beschreibbar zurückgegeben wird?
-
Speichere Zeiger statt Referenzen. Allerdings wird das in einer Katastrophe enden, weil du dann Zeiger auf temporäre Objekte speicherst und wohl später darauf zugreifen möchtest. Wenn du dir zum Beispiel mal die folgende Auswertung ansiehst:
B+Cgibt ein temporäres Objekt vom TypWrapper<TestClass, TestClass>zurück. Es speichert intern Zeiger aufBundC. Noch ist alles in Ordnung.A+(1.) gibt einWrapper<TestClass, Wrapper<TestClass, TestClass> >zurück.LHSzeigt aufA, was kein Problem ist.RHSzeigt dann allerdings auf das temporäre Objekt, welches bei 1. erzeugt und grundsätzlich auch gleich wieder zerstört wurde. Jeglicher spätere Zugriff darauf resultiert in undefiniertem Verhalten.
Dir bleibt somit nichts anderes übrig, als dass du Kopien machst oder einen C++0x Compiler mit Move-Konstruktoren verwendest.
Grüssli
-
Der aktuelle operator+ dürfte doch auch gar nicht kompilieren: Du nimmst non-const-Referenzen als Paramater entgegen, rufst die Funktion dann aber mit temporären Objekten auf. -> Error. Mit const-Referenzen würde das mit temporären Objekten wieder gehen.
-
l'abra d'or schrieb:
Der aktuelle operator+ dürfte doch auch gar nicht kompilieren: Du nimmst non-const-Referenzen als Paramater entgegen, rufst die Funktion dann aber mit temporären Objekten auf. -> Error. Mit const-Referenzen würde das mit temporären Objekten wieder gehen.
Richtig...deswegen frage ich ja um Rat...
Ich brauche nämlich nicht Konstante Rückgabewerte damit ich später die Daten noch verändern kann;
Gebe ich direkt eine Referenz, dann endet es direkt, wie Dravere es beschrieben hat, in einer Katastrophe.Das mit dem Move-konstruktor klingt viel versprechend. Habe mich da auch schon etwas eingelesen aber wie genau ich das,in diesem Beispiel mit den RValues machen soll, weis ich noch nicht...
-
Was spricht dagegen, einfach Werte zu verwenden? Keine Zeiger, keine Referenzen einfach Werte. Wenn sich im Nachhinein herausstellt, dass dies für einige Type zu inperformant ist (nach dem man gemessen hat, dass genau dass, das Problem ist), kann man den Type auf einfaches Kopieren hin optimieren.
mfg Torsten
-
Torsten Robitzki schrieb:
Was spricht dagegen, einfach Werte zu verwenden? Keine Zeiger, keine Referenzen einfach Werte. Wenn sich im Nachhinein herausstellt, dass dies für einige Type zu inperformant ist (nach dem man gemessen hat, dass genau dass, das Problem ist), kann man den Type auf einfaches Kopieren hin optimieren.
mfg Torsten"Testtype" ist der "Wert" und er ist ziemlich groß; kopieren kommt da nicht in Frage.
"Wrapper" dient letzendlich dazu, die "Werte" zu Ordnen und für "Templatemagie" aufzubereiten.
-
Schnupfbear schrieb:
"Testtype" ist der "Wert" und er ist ziemlich groß; kopieren kommt da nicht in Frage.
Dann optimiere den Typen doch für Kopieren. "copy on write" (COW) wäre da z.B. ein Stichwort. Du trennst den Typen in ein Body und ein Handel, wobei der Body mit einem Referenzzähler versehen ist. Bei schreibenden Zugriffen auf den Body über das Handle, guckst Du, ob der Body mehr als einmal referenziert wird. Ist dem so, machst Du Dir Deine eigene Kopie des Bodies. Der copy c'tor des handles sieht dann so aus, dass er den Zeiger auf den Body kopiert und dort die Anzahl der Referenzen um eins erhöht.
mfg Torsten
-
Wie wärs damit?
class IWrapper{}; template<class lhs , class rhs> class Wrapper : IWrapper { lhs & LHS; rhs & RHS; public: Wrapper(lhs & LHS, rhs & RHS) : LHS(LHS), RHS(RHS) {} /* IMPL... */ }; template<class lhs , class rhs, bool L = std::is_base_of<IWrapper,lhs>::value, bool R = std::is_base_of<IWrapper,lhs>::value > inline typename std::enable_if< !(L||R), Wrapper<lhs,rhs> > ::type&& operator+(lhs & LHS, rhs & RHS) { Wrapper<lhs,rhs> Result(LHS,RHS); /*.....*/ return std::move(Result); } template<class lhs , class rhs, bool L = std::is_base_of<IWrapper,lhs>::value, bool R = std::is_base_of<IWrapper,lhs>::value > inline typename std::enable_if< (!L&&R), Wrapper<lhs,rhs> > ::type&& operator+(lhs & LHS, rhs RHS) { Wrapper<lhs,rhs> Result(LHS,RHS); /*.....*/ return std::move(Result); } template<class lhs , class rhs, bool L = std::is_base_of<IWrapper,lhs>::value, bool R = std::is_base_of<IWrapper,lhs>::value > inline typename std::enable_if< (L&&!R), Wrapper<lhs,rhs> > ::type&& operator+(lhs LHS, rhs & RHS) { Wrapper<lhs,rhs> Result(LHS,RHS); /*.....*/ return std::move(Result); } template<class lhs , class rhs, bool L = std::is_base_of<IWrapper,lhs>::value, bool R = std::is_base_of<IWrapper,lhs>::value > inline typename std::enable_if< (L&&R), Wrapper<lhs,rhs> > ::type&& operator+(lhs LHS, rhs RHS) { Wrapper<lhs,rhs> Result(LHS,RHS); /*.....*/ return std::move(Result); } class Testclass {}; int main() { Testclass A; Testclass B; Testclass C; A+B+C; }Hat jemand ne elegantere Möglichkeit gefunden? - was wenns mehr als 2 Argumente sind?
Das hat leider nicht funktioniert, der Compiler war stets nicht in der lage die Funktion zu finden(auser man gibt die Parameter explizit an):template<bool Cond, class A, class B> struct IF { typedef A type; }; template<bool Cond, class A, class B> struct IF<false,A,B> { typedef B type; }; template<class lhs , class rhs, bool L = std::is_base_of<IWrapper,lhs>::value, bool R = std::is_base_of<IWrapper,lhs>::value > Wrapper<lhs,rhs> operator+( typename IF<L,lhs&,lhs>::type LHS , typename IF<R,rhs&,rhs>::type RHS )MFG
Speed
-
@Speed : funktioniert leider nur wenn Compiler-Optimierungen aktiviert sind(G++-4.5)
Torsten Robitzki schrieb:
Dann optimiere den Typen doch für Kopieren. "copy on write" (COW) wäre da z.B. ein Stichwort. Du trennst den Typen in ein Body und ein Handel, wobei der Body mit einem Referenzzähler versehen ist. Bei schreibenden Zugriffen auf den Body über das Handle, guckst Du, ob der Body mehr als einmal referenziert wird. Ist dem so, machst Du Dir Deine eigene Kopie des Bodies. Der copy c'tor des handles sieht dann so aus, dass er den Zeiger auf den Body kopiert und dort die Anzahl der Referenzen um eins erhöht.
mfg TorstenSehe es irgendwie nicht ein wieso ich ein Kopieroverhead in kauf nehmen soll, obwohl der Compiler ja tun könnte(könnte er?:-), was ich möchte.
Der Code Funktioniert ja, wenn man ihn in Zwischenschritte aufspaltet und die Ergebnisse einer Variable zuweist(ist uns sogar lieber, als viel rumzukopieren):
auto X = A+B; auto Y = X+C; auto Z = Y+D; //uswDann sollte man vielleicht wissen, dass eigentlich "Wrapper" dazu eingeführt worden ist, um ein paar Features durch "template-Magie" zu ermöglichen - ohne Kopieren zu müssen. Jetzt wollten wir zusätzliche Features, mit Schreiboperationen, einführen, da entschloss ich im "operator+" das "const&" in "&" umzuschreiben... naja und dann bin ich hierher gelandet ;P
LG