temporary als non-const-ref übergeben
-
Hallo zusammen,
ich benutze die Bibliothek Eigen für Matrizen und Vektoren und habe eine Funktion geschrieben, die die Werte eines solchen Vektors inplace verändert.
Oft will ich aber nicht den gesamten Vektor an die Funktion übergeben, sondern nur einen Teil (Segment) des Vektors, wofür Eigen eine nützliche segment()-Methode anbietet.
Der Rückgabewert von segment() ein ConstSegmentReturnType (typedef) ist, also Rückgabe eines art proxy-objekts per Wert.
Meine Funktion die einen Vektor inplace bearbeitet sieht sinngemäß so aus (laut einem Eigentutorial soll man Eigen::DenseBase als Typ verwenden, wenn man auch Segmente als Eingabe erlauben will):template<typename T> void inplaceF(Eigen::DenseBase<T>& v) { for(int i = 0; i < v.size(); ++i) { v(i)++; } }Das Problem ist nun, dass bei einem Aufruf
inplaceF(v.segment(0,1000));zunächst ein temporäres (proxy)-Objekt zurückgegeben wird, dass dann beim Aufruf der Funktion an eine nicht-const-Referenz gebunden wird, was (afaik) laut Standard nicht erlaubt ist.
Um das zu beheben habe ich bisher nur diese (unschöne) Möglichkeit gefunden (ungetestet):
SegmentReturnType dummy = v.segment(0,1000); inplaceF(dummy);Kennt ihr eine gute Möglichkeit, das zu beheben?
Natürlich könnte man jetzt auch sagen, dann soll die Funktion eben nicht inplace arbeiten, aber das möchte ich nunmal so haben.
-
Überladung für rvalues anbieten
template<typename T> void inplaceF(Eigen::DenseBase<T>&& v) { inplaceF(v); }
-
was natürlich nur unter C++0x funktioniert *seufz*. Es löst das Problem auch nicht direkt, da es nicht für alle temporären objekte sinnvoll ist (temporärer Vektor/temporäre Matrix). Da würde man schon gerne haben, dass der Compiler nicht schweigt.
Ich schlage mich auch mit dem Problem rum. Kurz gefasst: wenn dir Eigen nicht hilft, musst du immer irgendwelche Konstrukte dieser Art verwenden.
Wenn dir der explizite dummy zu viel Aufwand ist, zum Beispiel weil die Funktion häufig aufgerufen wird, ginge vielleicht noch sowas:
template<class T> struct Proxy:public T{ Proxy(T const& t):T(t){} }; template<class T> Proxy<T> proxy(T const& t){ return Proxy<T>(t);} //normale implmentation template<typename T> void inplaceF(Eigen::DenseBase<T>& v) { //... } //überladung für proxies template<typename T> void inplaceF(Proxy<T> v) { inplaceF(v); } //anwendung: inplaceF(proxy(v.segment(0,1000)))//edit besserer Name
-
Microsoft Compiler erlauben das Binden temporaerer Objekte an non-const-Referenzen
-
camper schrieb:
Überladung für rvalues anbieten
template<typename T> void inplaceF(Eigen::DenseBase<T>&& v) { inplaceF(v); }Danke, funktioniert super.
Einziger Nachteil, wie otze schon geschrieben hat, dass jetzt auch richtige temporäre Matrizen/Vektoren darauf binden können, aber ich glaube das kann ich verkraften, finde ich besser als das immer mit Proxy wrappen zu müssen.
-
Kann man da nicht per SFINAE irgendwie die zweite Überladung ausschließen, wenn der Typ keine Referenz-Semantik hat? Es gibt ja die "container"-Typen und diese Proxies, die auf die Elemente nur verweisen. Dass man im ersten Fall inplaceF für temporäre Objekte verbieten will, macht ja Sinn.
Ich habe Eigen bisher nur oberflächlich verwendet. Mir ist klar, dass da einiges and Template-Magie drin steckt und das lässt mich bzgl Aliasing aufpassen. Aber das war's auch schon.