Dynamisch Casten bei rein virtuelle Basisklasse



  • Abgesehen davon, dass das Beispiel bei mirnicht funktioniert(viele Fehler der letzten Zeile), glaube ich das Problem nun teilweise verstanden zu haben.
    Könnte man nicht das ganze ohne das Hilfstemplate Binder machen?

    Aber gut, den Aufruf (obj->*func)(str) muss man in eine Klasse schreiben mit oeprator(), sonst haben wir wieder kein Funktionsobjekt. Aber ginge hier nicht mit mem_fun & Co und dafür ohne Binder?



  • warum das bei dir nicht geht, kann ich ohne fehlerbeschreibung schlecht nachvollziehen, aber um zu deiner zweiten frage zu kommen, geht sicherlich, aber ich kann dir da nicht helfen, ich verwende nur boost::bind



  • warum das bei dir nicht geht, kann ich ohne fehlerbeschreibung schlecht nachvollziehen

    Kein Problem...

    [C++ Error] main.cpp(195): E2272 Identifier expected
    [C++ Error] main.cpp(195): E2188 Expression syntax
    [C++ Error] main.cpp(195): E2299 Cannot generate template specialization from 'Binder<Obj,Func>'
    [C++ Error] main.cpp(196): E2121 Function call missing )
    [C++ Error] main.cpp(196): E2379 Statement missing ;
    

    Ich fürchte er kriegt bool(Manipulator::*)(string&) nicht gebacken.
    Ich guckmal, ob ich's mit mem_fun hinbekomme
    bzw. ptr_fun



  • versuchs mal mit

    template< class Ret, class Class, class Arg >
    struct Binder
    {
    	Class* obj;
    	typedef Ret(Class::*mfunc)(Arg);
    	mfunc func;
    
    	Binder( Class* obj, mfunc func )
    		: obj( obj ), func( func )
    	{
    	}
    
    	bool operator()(string& str)
    	{
    		return (obj->*func)(str);
    	}
    };
    
    int main()
    {
    	vector<string> vec;
    	vec.push_back("hello");
    	Manipulator* m;
    	m = new Contains("hello");
    
    	find_if(vec.begin(),vec.end(), Binder< bool, Manipulator, string& >(m, &Manipulator::operator()) );
    }
    


  • Ja, nun geht es. Sieht auch schon viel besser aus und man versteht den Code deutlich besser...

    Vielen, vielen Dank!



  • Also mit
    mem_fun(&Manipulator::operator())
    oder
    pointer_to_unary_function<string,bool>(&Manipulator::operator() )
    geht es auch nich. Noch jemand ne Idee?



  • Dein Problem ist, daß die Funktionsobjekte von find_if standardmäßig per Wert übergeben werden - und eine abstrakte Klasse kannst du nicht per Wert übergeben. Aber du kannst explizit die für deine Zwecke richtige Version von find_if erzeugen lassen:

    Manipulator* m=new Contains(...);
    
    typedef vector<string>::iterator vecit;
    
    vecit pos=find_if<vec_it,Manipulator&>(vec.begin(),vec.end(),*m);
    

    (Referenzen auf abstrakte Objekte dürfen übergeben werden)



  • Also g++ moniert immer noch, dass Manipulator instanziert wird:

    stl_algo.h: In function `_InputIter std::find_if(_InputIter, _InputIter, _Predicate) [with _InputIter =
    Filter::filter(std::vector<std::string, std::allocator<std::string>
    >&)::vecit, _Predicate = Manipulator&]':
    ..\main.cpp:79:   instantiated from here
    
    stl_algo.h:318: error: cannot
    allocate an object of type `Manipulator'
    stl_algo.h:318: error:  because the following virtual functions are abstract:
    ..\main.cpp:26: error: 	virtual bool Manipulator::operator()(std::string&)
    


  • CStoll schrieb:

    Dein Problem ist, daß die Funktionsobjekte von find_if standardmäßig per Wert übergeben werden - und eine abstrakte Klasse kannst du nicht per Wert übergeben. Aber du kannst explizit die für deine Zwecke richtige Version von find_if erzeugen lassen:

    Manipulator* m=new Contains(...);
    
    typedef vector<string>::iterator vecit;
    
    vecit pos=find_if<vec_it,Manipulator&>(vec.begin(),vec.end(),*m);
    

    (Referenzen auf abstrakte Objekte dürfen übergeben werden)

    du dereferenzierst hier aber m, was du nicht darfst, du kannst kein Objekt von Manipulator haben.

    Die einzig richtige Lösung ist das Verwenden eines Binders und da wir das Rad nicht neu erfinden wollen, ist boost::bind der richtige Weg. boost::bind ist ne header-only library, also einfach auf boost.org die lib runterladen, entpacken und boost/bind.hpp inkludieren.


  • Mod

    leerer schrieb:

    CStoll schrieb:

    Dein Problem ist, daß die Funktionsobjekte von find_if standardmäßig per Wert übergeben werden - und eine abstrakte Klasse kannst du nicht per Wert übergeben. Aber du kannst explizit die für deine Zwecke richtige Version von find_if erzeugen lassen:

    Manipulator* m=new Contains(...);
    
    typedef vector<string>::iterator vecit;
    
    vecit pos=find_if<vec_it,Manipulator&>(vec.begin(),vec.end(),*m);
    

    (Referenzen auf abstrakte Objekte dürfen übergeben werden)

    du dereferenzierst hier aber m, was du nicht darfst, du kannst kein Objekt von Manipulator haben.

    selbstverständlich dürfen zeiger auf abstrakte klassen dereferenziert werden. das problem ist, dass standardalgorithmen eine kopie des vergleichsprädikates benutzen (andernfalls würde man der algorithmus das prädikat gar nicht nutzen können, da op() nicht const ist). und abstrakte klassen können nunmal nur als subobjekte instanziiert werden.

    Die einzig richtige Lösung ist das Verwenden eines Binders und da wir das Rad nicht neu erfinden wollen, ist boost::bind der richtige Weg. boost::bind ist ne header-only library, also einfach auf boost.org die lib runterladen, entpacken und boost/bind.hpp inkludieren.

    es gibt nie nur eine lösung. eine einfache (und wohl auch schnellere) variante - vorausgesetzt alle manipulatoren sind zustandslos - wäre die verwendung normaler funktionen statt funktionsobjekten. anstelle eines polymorphen funktionsobjektes würde dann ein normaler funktionszeiger benutzt werden. nebenbei ist find_if als nicht mutierender algorithmus klassifiziert und darf folglich nicht mit funktoren verwendet werden, die ihr argument modifizieren.



  • nebenbei ist find_if als nicht mutierender algorithmus klassifiziert und darf folglich nicht mit funktoren verwendet werden, die ihr argument modifizieren.

    Nicht, nein? Und wie macht sich das bei nicht Beachtung bemerkbar?


  • Mod

    nirsaja logged out schrieb:

    nebenbei ist find_if als nicht mutierender algorithmus klassifiziert und darf folglich nicht mit funktoren verwendet werden, die ihr argument modifizieren.

    Nicht, nein? Und wie macht sich das bei nicht Beachtung bemerkbar?

    undefiniertes verhalten. abhängig von implementation, prädikat und sequenz passiert möglicherweise gar nichts besonderes - oder der computer explodiert. (dass die formalen anforderungen an parameter einiger algorithmen strenger sind als sie sein müssten ist ein bekanntes problem - in gewissen grenzen kann man sie in der praxis auch schon mal ignorieren...) 😉


Anmelden zum Antworten