Kann man den Operator + bei vector<> überladen?
-
Du musst den Operator als freie Funktion und nicht als Memberfunktion implementieren.
-
SeppJ schrieb:
Jedoch würde ich bei Addition von vectoren intuitiv eher eine elementweise Addition erwarten.
Ich weiß nicht. vector ist so eine eierlegende Wollmilchsau.
Die elementweise Addition würde ich gerne bei valarray sehen. valvector?
-
Nexus schrieb:
drakon schrieb:
@rüdiger:
Warum verändert deine Funktion ein Argument? - Für den +-Operator würde ich da eher die Variante von ipsec bevorzugen, was auch eher dem Verhalten vonstd::stringentspricht.Das erste Argument wird kopiert. Teilweise ist es für den Compiler einfacher, unnötige Kopien wegzuoptimieren, wenn die Kopie implizit (über Parameter oder Rückgabewert) erfolgt.
Das Verhalten von rüdigers Funktion ist analog zum
operator+beistd::string.Stimmt. Hab da irgendwie ein & gesehen.
Elementweise Addition fände ich auch hier eher merkwürdig.
-
SeppJ schrieb:
Mir fällt auch gerade kein gutes Operatorsymbol für eine Union zweier Mengen ein, da ich eigentlich überall elementweise Operationen erwarten würde.
Wie wäre es mit
operator&oderoperator,? (Natürlich sollte man zu beiden noch einen Kommentar schreiben)
-
Aber gilt der Operator dann nicht für alle + Vector-Operatoren? Ich würde das ganze gerne auf eine spezielle Klasse beschränken. Der ganze Quatsch wird später mal Teil eines größeren Projektes, wo auch andere dran arbeiten. Will denen nicht meinen Operator aufdrängen.
Aber ansonsten läuft es super. Vielen lieben Dank für eure Hilfe!!!
Gruß
Thorsten
-
Dann lass die Deklaration im Header und mach lediglich eine Definition in der Quelldatei. Andere Dateien haben da dann keinen Zugriff drauf.
Alternativ wäre es noch eine Möglichkeit das in einen namespace zu packen, aber ich denke, dass das nicht nötig ist.
-
Nexus schrieb:
drakon schrieb:
@rüdiger:
Warum verändert deine Funktion ein Argument? - Für den +-Operator würde ich da eher die Variante von ipsec bevorzugen, was auch eher dem Verhalten vonstd::stringentspricht.Das erste Argument wird kopiert. Teilweise ist es für den Compiler einfacher, unnötige Kopien wegzuoptimieren, wenn die Kopie implizit (über Parameter oder Rückgabewert) erfolgt.
Das Verhalten von rüdigers Funktion ist analog zum
operator+beistd::string.ergänzend noch folgender Artikel
http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
-
rüdiger schrieb:
operator+ finde ich eigentlich unpassend, da a+b != b+a
(ok ist bei strings auch so. Aber da finde ich + auch unpassend)template<typename T, class Alloc> vector<T, Alloc> operator+(vector<T, Alloc> lhs, vector<T, Alloc> const &rhs) { lhs.reserve(lhs.size() + rhs.size()); lhs.insert(lhs.end(), rhs.begin(), rhs.end()); return lhs; }Ich denke nicht, dass
reservenotwendig ist. Ich würde mal davon ausgehen, dass, falls insert RandomAccess-Iteratoren bekommt, es selbst schlau genug ist, entsprechend Platz zu machen. Das geht ja eigentlich recht einfach über iterator_traits<Iter>::iterator_category und Tag-Dispatching. Gut, garantiert wird dies wahrscheinlich nicht, aber es macht IMHO eine gute StdLib-Implementierung aus. (Ich hab's in diesem Fall nicht wirklich getestet, aber ich weiß, dass zB in libstdc++ derartige Optimierungen en masse enthalten sind. std::copy kann z.B. u.U. auch zu einem memmove reduziert werden).Bzgl Performanz/Optimierung geht sogar noch einen Tucken besser:
template<typename T, class Alloc> vector<T, Alloc> operator+(vector<T, Alloc> lhs, vector<T, Alloc> const &rhs) { vector<T,Alloc> result; result.swap(lhs); result.insert(result.end(), rhs.begin(), rhs.end()); return result; // NRVO möglich }Jedoch werden die Elemente bei der Zuweisung in
c = a+b;noch unnötig kopiert. Da man vector<> nicht verändern kann, geht das meines Wissens nach auch nicht anders -- es sei denn, man arbeitet im C++0x Modus. Dann findet natürlich kein unnötiges Kopieren statt, weil die Elemente von(a+b)einfach nachc"umziehen".kk
-
shinji schrieb:
Viel lieber wäre mir aber solch eine Lösung:
vector<int> z; z = b + e + b;Die unnötige Kopie, von der ich vorhin sprach, lässt sich aber auch so umgehen:
vector<int> z = b + e + b;Tipp: Vermeide Definition mit Defaultinitialisierung + Zuweisung. Benutze gleich die richtige Initialisierung. Hier kann ein Compiler die unnötige temporäre Kopie, die sich aus (b+e+b) ergibt, wegoptimieren.
kk
-
also vektoren mit "+" aneinanderhängen ist doch sowieso schmarrn.
nicht umsonst nimmt man in java/c#/... einen string-builder statt dauernd strings mit "+" zusammenzuhängen.
-
hustbaer schrieb:
also vektoren mit "+" aneinanderhängen ist doch sowieso schmarrn.
nicht umsonst nimmt man in java/c#/... einen string-builder statt dauernd strings mit "+" zusammenzuhängen.Ich glaube nicht.
Man nimmt den Stringbuilder, weil er so toll wachsen kann wie ein std::vector oder std::string. Normale Strings können das nähmlich nicht.
Nur ist für viele Anfügungen der op+ nicht gut und der op+= ist besser.
-
drakon schrieb:
Alternativ wäre es noch eine Möglichkeit das in einen namespace zu packen, aber ich denke, dass das nicht nötig ist.
Gilt der Operator dann nur in dem namespace oder kann man dann folgendes schreiben:
std::vector<int> A, B, X; X = A std::+ B
-
wxSkip schrieb:
drakon schrieb:
Alternativ wäre es noch eine Möglichkeit das in einen namespace zu packen, aber ich denke, dass das nicht nötig ist.
Gilt der Operator dann nur in dem namespace oder kann man dann folgendes schreiben:
std::vector<int> A, B, X; X = A std::+ B
Weder noch. Man kann den operator nicht in std überladen, weils schlicht verboten ist, neue Definitionen in std zu packen. Templatespezialisierungen mal ausgenommen.
ns::+ funktioniert garnicht, das müsste man dann explizit schreiben alsX = ns::operator+(A, B)
alternativ kann man den Operator in den jeweiligen Scope oder Namespace importieren per using-Direktive.
-
pumuckl schrieb:
alternativ kann man den Operator in den jeweiligen Scope oder Namespace importieren per using-Direktive.
Das war meine Intention. Ich würde wahrscheinlich den namespace nehmen, wenn diese Überladung auch für andere Dateien von Interesse ist und die direkte Implementierung in die Quelldatei, wenn du das nur in einem File brauchst (weil da der namespace nicht viel bringt).
-
Man kann sich das auch alles sparen, und vernünftigerweise eine freie Funktion anstelle eines höchst fragwürdigen Operators verwenden.
-
hustbaer schrieb:
Man kann sich das auch alles sparen, und vernünftigerweise eine freie Funktion anstelle eines höchst fragwürdigen Operators verwenden.

Wenn ich jetzt nicht viel zu tun hätte, würde ich filisofisch werden, warum uns das nicht vorher eingefallen ist.
-
volkard schrieb:
filisofisch
Wenn dann: filosofisch oder vielohsofisch
-
drakon schrieb:
Dann lass die Deklaration im Header und mach lediglich eine Definition in der Quelldatei. Andere Dateien haben da dann keinen Zugriff drauf.
Alternativ wäre es noch eine Möglichkeit das in einen namespace zu packen, aber ich denke, dass das nicht nötig ist.
Ich möchte auch nochmal darauf hinweisen, dass ein solcher Operator nicht Teil der Schnittstelle von Vektoren im Sinne dieses Artikels ist. Er wird nicht über ADL gefunden und es kann sein, dass er durch einen anderen operator+ verdeckt wird -- je nachdem, wo man ihn deklariert und von wo aus man ihn benutzen will. In so einer Situation hilft auch keine using-Direktive sonder nur eine using-Deklaration.
kk
-
volkard schrieb:
hustbaer schrieb:
Man kann sich das auch alles sparen, und vernünftigerweise eine freie Funktion anstelle eines höchst fragwürdigen Operators verwenden.

Wenn ich jetzt nicht viel zu tun hätte, würde ich filisofisch werden, warum uns das nicht vorher eingefallen ist.Naja. Eigentlich wurde das ja bereits von Rüdiger als dritte Antwort angesprochen. Nicht direkt, aber prinzipiell hat er genau das damit gesagt.
Allerdings bin ich für meinen Teil davon ausgegangen, dass der Fragesteller sich durchaus bewusst ist, dass man da eine freie Funktion nehmen kann. Über die Gründe lassen sich natürlich diskutieren, aber das ist ja eigentlich ein anderes Problem.
-
volkard schrieb:
hustbaer schrieb:
Man kann sich das auch alles sparen, und vernünftigerweise eine freie Funktion anstelle eines höchst fragwürdigen Operators verwenden.

Wenn ich jetzt nicht viel zu tun hätte, würde ich filisofisch werden, warum uns das nicht vorher eingefallen ist.v = v1 + v2 + v3 + v4 + v5; // Oder: v = add_vector(add_vector(add_vector(add_vector(v1, v2), v3), v4), v5);