Prädikat für die Funktion remove_copy_if negieren



  • Hallo zusammen,

    ich möchte für die Funktion remove_copy_if aus dem Namensraum std ein Prädikat negieren. Wie ich recht schnell festgestellt hab, reicht ein einfaches '!' nicht.

    Somit habe ich folgendes gebastelt bzw. aus der Literatur entnommen:

    Prädikat:

    bool isPrim(unsigned int z)
    {
    	unsigned int stop = sqrt(static_cast<double> (z));
    
    	for (unsigned int i = 2; i <= stop; i++)
    	{
    		if (z % i == 0)
    			return false;
    	}
    	return true;
    }
    

    Negator:

    template<typename Predicate>
    UnaryNegate<Predicate> not1(const Predicate &pred)
    {
    	return UnaryNegate<Predicate> (pred);
    }
    

    Klasse Unary Negate

    template<typename Predicate>
    class UnaryNegate: public unary_function<typename Predicate::argument_type,
    		bool>
    {
    	public:
    		explicit UnaryNegate(const Predicate &pre) :
    			p(pre)
    		{
    
    		}
    		virtual ~UnaryNegate();
    
    		bool operator()(const typename Predicate::argument_type& x) const
    		{
    			return !p(x);
    		}
    
    	private:
    		Predicate p;
    };
    

    Und zusammen wie folgt angewandt:

    unsigned int numbers[] = { 2, 6, 29, 30, 45, 49, 50 };
    
    //Number of integers
    int n = sizeof numbers / 4;remove_copy_if(numbers, numbers + n, ostream_iterator<unsigned int> (cout, ","), not1(isPrim));
    

    Mein Compiler sagt mir nun folgendes:

    **** Build of configuration Debug for project Standardbibiothek Beispiele ****

    make all
    Building file: ../src/Kapitel3.cpp
    Invoking: GCC C++ Compiler
    g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/Kapitel3.d" -MT"src/Kapitel3.d" -o"src/Kapitel3.o" "../src/Kapitel3.cpp"
    /usr/include/c++/4.0.0/bits/stl_function.h: In instantiation of 'std::unary_negate<bool ()(unsigned int)>':
    ../src/Kapitel3.cpp:106: instantiated from here
    /usr/include/c++/4.0.0/bits/stl_function.h:314: error: 'bool ()(unsigned int)' is not a class, struct, or union type
    /usr/include/c++/4.0.0/bits/stl_function.h:322: error: 'bool ()(unsigned int)' is not a class, struct, or union type
    /usr/include/c++/4.0.0/bits/stl_function.h:316: error: field 'std::unary_negate<bool ()(unsigned int)>::_M_pred' invalidly declared function type
    /usr/include/c++/4.0.0/bits/stl_algo.h: In function '_OutputIterator std::remove_copy_if(_InputIterator, _InputIterator, _OutputIterator, _Predicate) [with _InputIterator = unsigned int*, _OutputIterator = std::ostream_iterator<unsigned int, char, std::char_traits<char> >, _Predicate = std::unary_negate<bool ()(unsigned int)>]':
    ../src/Kapitel3.cpp:106: instantiated from here
    /usr/include/c++/4.0.0/bits/stl_algo.h:1074: error: no match for call to '(std::unary_negate<bool ()(unsigned int)>) (unsigned int&)'
    make: *** [src/Kapitel3.o] Error 1

    Mein Problem ist nun, dass ich nicht weiß wie ich das ganze angehen soll bzw. wie man am besten heraus findet, wo der Fehler liegt ohne alles 1 zu 1 abzuschreiben(aus Literatur etc.). Gebt ihr mir einen Tipp?

    Viele Grüße
    MM



  • du brauchst dir dein negations-Prädikat nicht selber zu schreiben, das gibts in der Standardbibliothek schon, im header <functional>, und es heißt std::not1. Das ist auch das was dein Compiler da benutzt.
    Versuch mal, statt isPrim direkt zu übergeben, einen Pointer darauf zu übergeben:

    remove_copy_if(numbers, 
                   numbers + n, 
                   ostream_iterator<unsigned int> (cout, ","), 
                   not1(&isPrim));  // <-!!!
    

  • Administrator

    Der Fehler ist einfach und blöd. Man darf keine Funktion übergeben, sondern muss aus der Funktion zuerst ein pointer_to_unary_function Objekt erstellen.

    remove_copy_if(numbers, 
                   numbers + n, 
                   ostream_iterator<unsigned int> (cout, ","), 
                   not1(ptr_fun(isPrim)));
    

    Wie du siehst, erreicht man die mit std::ptr_fun .

    Unter anderem deshalb freuen sich alle über Boost.Bind , std::tr1::bind oder dem C++0x std::bind .

    Edit: Rechtschreibefehler.

    Grüssli 🙂



  • super, vielen Dank 🙂 Klappt nun.

    Viele grüße
    MM


Anmelden zum Antworten