unresolved overloaded function type bei benutzung von for_each und überladener Memberfunktion
-
Tach auch,
Wenn ich eine memberfunktion überlade, dass sie einmal ein einzelnes Element und einmal einen vector von Elementen annehmen kann, wieso kann ich dann nicht die einzelfunktion mit for_each aufrufen?
class Foo { void bar(const baz&) { do_something(); } void bar(const std::vector<baz>& vec) { std::for_each(vec.begin(), vec.end(), std::bind1st(&Foo::bar, this)); } };g++ 4.4.0 meint dazu:
error: no matching function for call to ‘bind1st(<unresolved overloaded function type>, Foo* const)’Ideen?
-
Schau dir mal
std::mem_fun()an.
-
geht auch nicht:
error: no matching function for call to ‘mem_fun(<unresolved overloaded function type>)’
-
Ja, war auch Unsinn.
mem_fun()braucht man, um Memberfunktionen der Elemente selbst aufzurufen. Sorry, ich hab dein Problem falsch gelesen.Mit Überladungen haben Funktionsobjekte so ihre Schwierigkeiten. Bei
&Foo::barist ja nicht ohne Weiteres klar, welche Funktion gemeint ist. So funktioniert z.B. auchstd::tr1::bind()nicht.Ich denke, um eine gute alte Schleife wirst du nicht herumkommen, wenn die Methoden gleich heissen sollen.
-
Boah wie ich das hasse. C++/STL hat soooo viele tolle Features, aber wenn man sie mal so richtig nutzen will, geht's nicht.
-
Nicht verzweifeln. So gehts:
void bar(const std::vector<int>& vec) { void (Foo::*first)(const int&) = &Foo::bar; std::for_each(vec.begin(), vec.end(), std::tr1::bind(first, this, _1)); }Da ich
std::bind1sthasse und es verbuggt ist, bin ich mir nicht sicher, ob es damit auch geht. Abertr1::bindist eh besser.
-
Okay, danke.
Ich revidiere obige Aussage zu folgender:
"Boah wie ich das hasse. C++/STL hat soooo viele tolle Features, aber wenn man sie mal so richtig nutzen will, muss man Code produzieren, den kein Mensch mehr lesen kann."
-
Ich find das eigentlich ganz lesbar. Ist aber wahrscheinlich Gewöhnungssache.
Was es halt für dich schwer zu lesen macht ist die Tatsache, dass da in der Zeile sehr viel drin steckt. Schreib das mal auf "deine" Art aus und dann merkst du, dass da eigentlich sehr viel eleganz drin ist das in einer Zeile zu machen. Und es wird dir dann auch jeder bestätigen, dass der Einzeiler sehr viel klarer ist, als irgendwelche Schleifengebastlereien, wo jeder Leser zuerst alles anschauen muss, bis er überhaupt verstehen kann, was es macht.
Hier habe ich genau diese eine Zeile angeschaut und wusste, was sie machen sollte. Bei einem Schleifenkonstrukt hätte ich zuerst mal die Bedingung anschauen müssen, wann/wo inkrementiert wird und schlussendlich noch den eigentlichen Code. Wenn das mal keine Zeitersparnis ist.
-
PhilippM schrieb:
"Boah wie ich das hasse. C++/STL hat soooo viele tolle Features, aber wenn man sie mal so richtig nutzen will, muss man Code produzieren, den kein Mensch mehr lesen kann."
Du findest einen Memberfunktionszeiger unlesbar? Wahrscheinlich nur, weil du noch nicht oft damit gearbeitet hast. Dabei ist das etwas ziemlich Zentrales, wenns in Richtung STL und funktionales Programmieren geht. Die drei Möglichkeiten für Callables sind nämlich Funktionszeiger, Memberfunktionszeiger und Funktionsobjekte. Für effizientes Arbeiten mit den STL-Algorithmen würde ich deren Kenntnis voraussetzen.
Bedenke ausserdem, dass der gezeigte Code sehr kompakt ist. Da die beiden Methoden gleich heissen, brauchst du eine Zusatzinformation, um sie auseinanderzuhalten. Und das ist eben die Signatur von
bar, welche in den Typ des Funktionszeigers einfliesst.
-
Ja. Die Überladung ist unglücklich. Allerdings kannst du einen kleinen Trick verwenden, wenn du das noch reduzieren möchtest:
void bar(const std::vector<int>& vec, int i = 0) { std::for_each(vec.begin(), vec.end(), std::tr1::bind(&foo::bar, this, _1)); }Obwohl ich das ein wenig merkwürdig finde, dass es funktioniert (MSVC).
Würde sogar behaupten, dass das ein Bug ist, da sich die Funktion eigentlich gleich verhalten müsste, als ob da kein Parameter ist. Wäre mal etwas, um mal wieder den Standard zu wälzen.