bind2nd problem
-
hi leute,
ich würde zur übung gerne einen eigenen kleinen quicksort schreiben:struct some_type; typedef some_type value_type; typedef std::vector <value_type> container_type; typedef container_type::iterator iterator_type; typedef bool (* compare_type) (value_type const &, value_type const &); bool compare (value_type const & lhs, value_type const & rhs); void sort (iterator_type begin, iterator_type end, compare_type compare); void sort (iterator_type begin, iterator_type end, compare_type compare) { if (begin != end) { iterator_type pivot = std::partition(begin, end, std::bind2nd(compare, *begin)); sort (begin, pivot, compare); sort (std::max(begin + 1, pivot), end, compare); } }die hilfsfunktion compare:
bool compare (value_type const & lhs, value_type const & rhs) { return lhs.key < rhs.key; }anscheinend kann ich "compare" als binäre funktion nicht direkt an "partition" übergeben, da eine unäre funktion erwartet wird. daher wird bind2nd verwendet.
der compiler spuckt nun folgende fehlermeldung aus:
error C2825: '_Fn2': must be a class or namespace when followed by '::'
was mache ich falsch? warum nimmt bind2nd mein compare nicht an?
die schnittstelle von compare darf übrigens nicht verändert werden... wie bringe ich den code zum laufen?
-
Anstelle des Typedefs solltest du ein Template verwenden, das macht die Sache schonmal viel flexibler. Hab nicht weiter hingeschaun, hoffe das hilft dir mal weiter.
Gruß
-
thomassteiner schrieb:
iterator_type pivot = std::partition(begin, end, std::bind2nd(compare, *begin));anscheinend kann ich "compare" als binäre funktion nicht direkt an "partition" übergeben, da eine unäre funktion erwartet wird. daher wird bind2nd verwendet.
der compiler spuckt nun folgende fehlermeldung aus:
error C2825: '_Fn2': must be a class or namespace when followed by '::'
was mache ich falsch? warum nimmt bind2nd mein compare nicht an?
Hi Thomas,
std::bind2nd erwartet lt. Standard bestimmte typedefs. Dazu werden Adapter zur Verfügung gestellt, die diese typedefs generieren. Dein Helferlein heißt hier: std::ptr_fun, der einen pointer_to_binary_function generiert.
iterator_type pivot = std::partition(begin, end, std::bind2nd( std::ptr_fun( compare ), *begin));Dummerweise landest Du dann beim 'reference to reference'-Problem; siehe hier http://www.boost.org/libs/utility/call_traits.htm.
thomassteiner schrieb:
die schnittstelle von compare darf übrigens nicht verändert werden... wie bringe ich den code zum laufen?
am besten Du nimmst gleich boost::bind

Gruß
Werner
-
Am besten nimmst du gleich einen Funktor.
-
Genau. Und den musst du von binary_function ableiten, damit er adaptable wird (das ist das, was bind2nd verlangt).
-
Ringding schrieb:
Genau. Und den musst du von binary_function ableiten, damit er adaptable wird (das ist das, was bind2nd verlangt).
Im Prinzip ja, aber doch wieder nein :xmas1: , weil so landet man ohne besondere Verenkungen wieder beim 'reference of reference'-Problem. Wenn schon Funktor, dann ein Funktor der das bind2nd mit einschließt. Etwa so:
template< typename T > struct Comp { typedef bool (*comp_type)( const T& a, const T& b ); Comp( comp_type comp, const T& fix ) : m_comp( comp ), m_fix( fix ) {} bool operator()( const T& x ) const { return (*m_comp)( x, m_fix ); } private: comp_type m_comp; T m_fix; }; // Factory-Funktion template< typename T > Comp< T > make_comp( typename Comp< T >::comp_type comp_func, const T& fix ) { return Comp< T >( comp_func, fix ); }und so in der Anwendung
// iterator_type pivot = std::partition(begin, end, std::bind2nd(compare, *begin)); iterator_type pivot = std::partition(begin, end, make_comp( compare, *begin ) );.. mit boost wär' alles einfacher, hier schreibt man einfach
iterator_type pivot = std::partition(begin, end, boost::bind( compare, _1, *begin ) );:xmas2: Werner
PS.: übrigens; die Weihnachts-Icons sind

-
Da boost::bind seit längerem definitiv im TR1 des ISO C++ drin ist, kann man es bedenkenlos benutzen. Wird also eh bald bei jedem Compiler (auch VC++) mit beiligen. Nur halt unter dem Namespace std::tr1 und nicht boost::.