Kopie mit auto innerhalb eines Ausdrucks?
-
Hi,
ich möchte innerhalb eines Ausdrucks eine Kopie eines Ausdrucks erzeugen, möchte den Typ aber über auto implizieren.
Also in etwa so:
someFunc(auto(getSomeResult()));Scheint aber nicht zu klappen (VC10). Die Kopie benötige ich, weil someFunc in diesem speziellen Fall das verändert, was getSomeResult() zurückgibt.
Der äquivalente Zweizeiler wäre:
auto result = getSomeResult(); someFunc(result);Kann ich das irgendwie ohne Zweizeiler machen?
Danke

-
Hä?
Wie sieht denn deine Funktion aus? Entweder muss der Parameter ja per Referenz oder Value übergeben werden. Und da du den Parameter ja intenr verädnerst und dann wieder nach außen gibst, bietet sich eigentlich ein Call-By-Value an.
Foo doShit(Foo f) { f.changeMe(); return f; } int main() { Foo x = doShit( getObj() ); }Nix auto, nix sonstwas.
Wenn deine Funktion eine Referenz erwartet, dann kansnt du nicht das Rückgabeobjekt deiner getSomeResult-Funktion nutzen, denn das ist ein RValue.
-
Wie geschrieben, in diesem speziellen Fall ist das Resultat von getSomeResult() eine Referenz auf das, was someFunc verändert. Das ist aber nicht immer der Fall, sodass eine Kopie normalerweise unnötigen Aufwand produziert. someFunc erwartet daher eine const Referenz, um die Kopie zu vermeiden, das möchte ich auch beibehalten.
Wenn deine Funktion eine Referenz erwartet, dann kansnt du nicht das Rückgabeobjekt deiner getSomeResult-Funktion nutzen, denn das ist ein RValue.
Kapier ich nicht, wieso sollte das nicht gehen?
Kapier ich jetzt doch, aber wie gesagt: Es ist hier mehr oder minder "Zufall", dass getSomeResult() das zurückgibt, worauf someFunc(.) operiert. Für andere Parameter ist das anders.Bitte einfach Mal hinnehmen, dass der Fall so Sinn ergibt und ich als Übergabeparameter eine Kopie von getSomeResult() übergeben möchte.
-

Suchst du das?someFunc( static_cast<foo>(getSomeResult()) );
-
Im Prinzip schon, aber ich will ja auto verwenden, um nicht den gesamten Typnamen auszuschreiben (aus dem Kontext mit korrekten Funktionsnamen geht der Typ implizit eindeutig hervor, daher finde ich das okay, aber ich will mir Templateparameterangaben usw. sparen, wie das eben so ist).
Wie gesagt, ich suche einen kurzen Einzeiler für den äquivalenten Zweizeiler aus meinem OP, dafür hätte ich meine Syntax eigentlich intuitiv gefunden, leider geht die nur eben nicht.
-
Eisflamme schrieb:
Im Prinzip schon, aber ich will ja auto verwenden, um nicht den gesamten Typnamen auszuschreiben (aus dem Kontext mit korrekten Funktionsnamen geht der Typ implizit eindeutig hervor, daher finde ich das okay, aber ich will mir Templateparameterangaben usw. sparen, wie das eben so ist).
Wie gesagt, ich suche einen kurzen Einzeiler für den äquivalenten Zweizeiler aus meinem OP, dafür hätte ich meine Syntax eigentlich intuitiv gefunden, leider geht die nur eben nicht.
someFunc( static_cast<decltype(getSomeResult())>(getSomeResult()) );Ich sehe keine andere Möglichkeit.

-
Das Problem an der Sache ist ja, dass du einen Wert brauchst. Ein Ausdruck resultiert in einem Wert, eine Variablendefinition nicht, darum kannst du bei einem Funktionsaufruf keine Variable einführen. der Kommaoperator wird da wohlo auch nicht helfen, der will auch nur Ausdrücke. Wenn du also den Typ nicht explizit angeben willst, musst du wohl
decltyperausholen, und da du keine Variable haben kannst, musst du die Funktion 2x aufrufen. Und die Funktion mit by-value und by-reference zu überladen, ist zwar Möglich, führt doch aber schlussendlich nur zu Mehrdeutigkeiten. Ob es da was type_traits-technisches gibt, keine Ahnung. Schlussendlich wirst du wohl dein Design überarbeiten müssen.
-
out schrieb:
someFunc( static_cast<decltype(getSomeResult())>(getSomeResult()) );Das bringt nichts, da decltype dir hier auch einen Referenz-Typen geben wird.
-
Du veränderst etwas hinter einer const-reference?
-
Ich kenne dein problem, tritt bei mir auch immer wieder mal auf wenn ich expression templates verwende. Ich würde den Umweg über eine Funktion gehen.
template<class T> T autocopy(T&& original){ return original;//funktioniert das so? ich hab keine Ahnung von C++11 } someFunc( autocopy(getSomeResult()) );
-
cooky451:
Habe ich nie gesagt. Es trifft nur je nach Parameter zufällig auf dasselbe. Um den Kontext kurz zu schaffen: In meinem Fall liefert getSomeResult() die ChildIndices eines Nodes, während someFunc Indices eines Nodes löscht. Zum Löschen wird aber der Vektor, der an someFunc übergeben wird, iteriert. Wenn ich mit Referenzen ohne Kopie arbeite, wird während dem Löschvorgang natürlich der durch getSomeResult zurückgegebene Vektor mit ChildIndices manipuliert, was aber die die Iteratoren in der Schleife über die zu löschenden Indices zerstört.otze:
Ja, so was ähnliches hatte ich auch als Lösung im Kopf. Aber da die andere Variante eben auch nur ein Zweizeiler ist, sehe ich den großen Vorteil daran eher nicht.Dann aber eine andere Frage: Ich verstehe die Logik nicht, wieso auto nicht funktioniert. Eine Zeile:
auto someThing = getSomeFunc();erzeugt ja auch eine Variable vom Typ des Rückgabewertes und schafft es gleichzeitig eine Zuweisung zu erreichen.
Ebenso wie ich
SomeType(func())schreiben kann, um eine Kopie zu initialisieren, welche ich direkt an eine Funktion übergeben kann, dürfte es doch auch "theoretisch" möglich seinauto(func())zu schreiben, die Informationen müssen dem Compiler ja ganz genau so vorliegen, spricht doch also nichts dagegen.Also das ist jetzt eine andere Frage. Dass mein Problem nicht mit Einzeiler gelöst werden kann, weiß ich jetzt. Aber was spricht gegen meine präferierte Syntax?
-
Es spricht nichts dagegen, es hat nur einfach niemand proposed. Schreib halt ein Proposal.
-
Wo kann ich das denn machen?Okay, das war leicht googlebar. Vielleicht mache ich das Mal, danke.

-
cooky451 schrieb:
Du veränderst etwas hinter einer const-reference?
Durchaus moeglich.
template<class T> T autocopy(T&& original){ return original;//funktioniert das so? ich hab keine Ahnung von C++11 }Nein, das funktioniert nicht immer. T wird zum Referenztypen deduziert, falls das Argument kein rvalue ist.
Loesung:template<class T> typename std::remove_reference<T>::type autocopy(T&& original) { return original;// funktioniert das so? ich hab keine Ahnung von C++11 (habe ich absichtlich stehen lassen :) ) }(Ungetestet)
Ich wuerde es uebrigensmake_temporarynennen
Das ist AFAICS auch die beste Loesung fuer einen Einzeiler (wobei ich sicher bin, das geht schooner).
Allgemein wuerde ich den zweizeiler vorziehen.
-
Eisflamme schrieb:
Aber was spricht gegen meine präferierte Syntax?
Ich finde sie kryptisch und redundant.
foo a, b = std::move(a); bar x, y = (auto&&)x; // ???
-
camper schrieb:
Eisflamme schrieb:
Aber was spricht gegen meine präferierte Syntax?
Ich finde sie kryptisch und redundant.
Deine Meinung ist kein Problem fuer mich.
Edit: Das Beispiel war falsch, never mind.
-
Gut, hast schon Recht, dass man für fast alle Fälle Redundanz hat. Nur wenn man es so einsetzt, wie es nicht gedacht ist, ist dann das Argument wirklich stark? Und Kryptik... das ist bei C++ irgendwie mittlerweile für mich kein Argument mehr.
In Deinem Beispiel würde halt eben erst der auto-Ausdruck und dann - basierend auf dem Resultat - die initiale Zuweisung an y erfolgen. Wo ist dort denn das Problem?
Habe Mal versucht es im Proposal-Google-Forum zu posten. Ich finde den Beitrag aber nicht wieder. Vermutlich wird der geprüft oder es ist etwas schief gelaufen. Mal abwarten.
-
Wo ist dort denn das Problem?
Es gibt keines.
Und Kryptik... das ist bei C++ irgendwie mittlerweile für mich kein Argument mehr.
Gerade wenn die Sprache doch schon kryptisch ist, sollte man darauf besonders achten.

-
Lass es leserlich und verständlich.