std::distance und size()
-
mean_user schrieb:
mean ist kein besonders gutes Beispiel für eine generische Funktion.
std::vector<int> v{1,2}; double m = mean(begin(v), end(v)); assert(m == 1.5); // fail!Ja und, warum soll das jetzt irgendwie schlecht sein?
Ist doch klar dass wenn du ints aufaddierst und dann teilst keinen korrekten double Wert kriegst. Generisch heißt doch nicht dass ein Typ (bzw. Ergebnis) beliebig konvertierbar sein muss.
Meiner Meinung nach ist das ein perfektes Beispiel für eine generische Funktion, da sie sowohl den Typen als auch den Container weg abstrahiert, und zwar automatisch und nicht wie etwa
std::accumulatedurch einen nervigen extra Parameter.
-
Uebergib accumulate halt ne Lambda:
T count = 0; return accumulate(s, e, T(0), [&](T a, T b){ ++count; return a + b; }) / count;
-
*Edit
Hier stand völliger Unsinn.
-
Kellerautomat schrieb:
Uebergib accumulate halt ne Lambda:
T count = 0; return accumulate(s, e, T(0), [&](T a, T b){ ++count; return a + b; }) / count;Öhm...
-
happystudent schrieb:
Wollte halt std::accumulate verwenden weil das anscheinend noch irgendwelche internen Optimierungen durchführt die sich mir nicht so ganz erschließen (siehe hier).
Ha??
Kellerautomat schrieb:
lamda
Keine gute Idee, falls accumulate unerschließliche Optimierungen machen darf.
-
UB schrieb:
Kellerautomat schrieb:
Uebergib accumulate halt ne Lambda:
T count = 0; return accumulate(s, e, T(0), [&](T a, T b){ ++count; return a + b; }) / count;Öhm...
Speicher es halt in ne Variable und gib dann sum / count zurueck. Kommt doch aufs selbe raus

-
Man könnte mal so etwas probieren (habs nicht gross getestet, ist nur so hingeklatscht, um die Idee zu geben):
template <typename Iter> double mean(Iter first, Iter last) { auto accumulator = [](std::pair<double,size_t> p, double val) { p.first += val; ++p.second; return p; }; auto acc_pair = std::accumulate(first, last, std::make_pair(0.0, 0), accumulator); return acc_pair.first / acc_pair.second; }Bringt aber auch einen Overhead mit, den man wahrscheidlich vermeiden möchte.
Bin mir auch nicht ganz sicher ob das wirklich funktioniert mit den Optimierungen, die
std::accumulateverwendet. Wenns falsch ist wirds bestimmt gleich gesagt
-
icarus2 schrieb:
Bringt aber auch einen Overhead mit, den man wahrscheidlich vermeiden möchte.
Und zwar welchen Overhead ausser dem Hardcoden von double?
-
volkard schrieb:
Ha??
Naja, das war doch der Konsens des Threads oder? Zumindest hatte ich das so verstanden:
SeppJ schrieb:
Wenn du nun sagst, dass dein Iterator mehr kann, dann merkt das accumulate das und wählt eine entsprechend raffiniertere Implementierung, die dies ausnutzt. Wenn dein Iterator dann aber deine Versprechen nicht halten kann, kommt es zum beobachteten Fehler.
Also irgendeinen Grund muss es ja geben dass std::accumulate den operator< braucht und damit von dieser Referenz-Implementierung dahingehend abweicht.
Das mit dem lambda werd ich mal austesten, bin ich nicht selbst drauf gekommen^^
-
volkard schrieb:
Kellerautomat schrieb:
lamda
Keine gute Idee, falls accumulate unerschließliche Optimierungen machen darf.
Darf es nicht (mehr):
§26.7.2 Accumulate schrieb:
Effects:
Computes its result by initializing the accumulator acc
with the initial value init and then modifies it with acc = acc + *i or acc = binary_op(acc, *i) for every iterator i in the range [first,last) in order.
-
Nathan schrieb:
Darf es nicht (mehr):
Ok, also auf gut deutsch es würde eh keinen Unterschied machen ob std::accumulate oder selbstgebaute Schleife? Weil dann könnte man sich den Stress ja eh sparen^^