Problem binding a predicate to random_shuffle()

Good day. After an initial post on the comp.lang.c++ usergroup, I was pointed to using boost::bind for binding member functions as predicates for STL functions (original example applied to sort()). The technique to use Boost's bind() works well, except when used with STL's random_shuffle(). The following code demonstrates a working call (on sort()) and a call that generates an error (on random_shuffle()), both using the same technique. The code: #include <algorithm> #include <functional> #include <vector> #include <boost/bind.hpp> using namespace std; class Foo { public: Foo() { for (int i=0; i < 5; i++) { dataVector.push_back(i*10); idVector.push_back(i); } } bool isLess(int leftID, int rightID) { return (dataVector[leftID] < dataVector[rightID]); } int customRand(int n) { return (rand() % n); } void mySort() { sort(idVector.begin(), idVector.end(), boost::bind(&Foo::isLess, this, _1, _2)); } void myShuffle() { random_shuffle(dataVector.begin(), dataVector.end(), boost::bind(&Foo::customRand, this, _1)); } private: vector<int> dataVector; vector<int> idVector; }; int main(int argc, char** argv) { Foo myObj; myObj.myShuffle(); myObj.mySort(); return 0; } The error: sort.cpp: In member function `void Foo::myShuffle()': sort.cpp:33: error: no matching function for call to `random_shuffle(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, boost::_bi::bind_t<int, boost::_mfi::mf1<int, Foo, int>, boost::_bi::list2<boost::_bi::value<Foo*>, boost::arg<1> > >)' /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_algo.h:1766: note: candidates are: void std::random_shuffle(_RandomAccessIterator, _RandomAccessIterator, _RandomNumberGenerator&) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, _RandomNumberGenerator = boost::_bi::bind_t<int, boost::_mfi::mf1<int, Foo, int>, boost::_bi::list2<boost::_bi::value<Foo*>, boost::arg<1> > >] The code compiles and runs fine using VC7.1 (Visual Studio 2003), but gives an error using g++ (GCC) 3.4.4 (cygming special). Any help will be greatly appreciated. Kind regards, Nelis Franken PS: A follow-up post on the exact same problem to comp.lang.c++ directed me to post it on the Boost list, since it was deemed off-topic. I hope someone else on this list has had a similar STL problem with random_shuffle() and boost::bind?

The problem may be that int and ptrdiff_t are distinct types on your platform. Try the following: ptrdiff_t customRand(ptrdiff_t n) { return (rand() % n); } --Johan Råde

Thanks for the suggestion Johan, but unfortunately that doesn't work either. The error remains the same when int is replaced by ptrdiff_t instead. I noticed a different error if I explicitly refer to std::random_shuffle (as opposed to just random_shuffle). The "new" errors (when using std::random_shuffle, and int instead of ptrdiff_t) are: (apologies for the extensive error listing) stl_sort.cpp:47: error: invalid initialization of non-const reference of type 'boost::_bi::bind_t<int, boost::_mfi::mf1<int, Foo, int>, boost::_bi::list2<boost::_bi::value<Foo*>, boost::arg<1> > >&' from a temporary of type 'boost::_bi::bind_t<int, boost::_mfi::mf1<int, Foo, int>, boost::_bi::list2<boost::_bi::value<Foo*>, boost::arg<1> > >' /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_algo.h:1766: error: in passing argument 3 of `void std::random_shuffle(_RandomAccessIterator, _RandomAccessIterator, _RandomNumberGenerator&) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, _RandomNumberGenerator = boost::_bi::bind_t<int, boost::_mfi::mf1<int, Foo, int>, boost::_bi::list2<boost::_bi::value<Foo*>, boost::arg<1> > >]' /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_algo.h: In function `void std::random_shuffle(_RandomAccessIterator, _RandomAccessIterator, _RandomNumberGenerator&) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> >
, _RandomNumberGenerator = boost::_bi::bind_t<int, boost::_mfi::mf1<int, Foo, int>, boost::_bi::list2<boost::_bi::value<Foo*>, boost::arg<1> > >]': stl_sort.cpp:47: instantiated from here /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_algo.h:1775: error: no match for call to `(boost::_bi::bind_t<int, boost::_mfi::mf1<int, Foo, int>,boost::_bi::list2<boost::_bi::value<Foo*>, boost::arg<1> > >) (int)' /usr/include/boost-1_33_1/boost/bind/bind_template.hpp:18: note: candidates are: typename boost::_bi::result_traits<R, F>::type boost::_bi::bind_t<R, F, L>::operator()() [with R = int, F = boost::_mfi::mf1<int, Foo, int>, L = boost::_bi::list2<boost::_bi::value<Foo*>, boost::arg<1> >] /usr/include/boost-1_33_1/boost/bind/bind_template.hpp:24: note: typename boost::_bi::result_traits<R, F>::type boost::_bi::bind_t<R, F, L>::operator()()const [with R = int, F = boost::_mfi::mf1<int, Foo, int>, L = boost::_bi::list2<boost::_bi::value<Foo*>, boost::arg<1> >] /usr/include/boost-1_33_1/boost/bind/bind_template.hpp:30: note: typename boost::_bi::result_traits<R, F>::type boost::_bi::bind_t<R, F, L>::operator()(A1&) [with A1 = int, R = int, F = boost::_mfi::mf1<int, Foo, int>, L = boost::_bi::list2<boost::_bi::value<Foo*>, boost::arg<1> >] /usr/include/boost-1_33_1/boost/bind/bind_template.hpp:36: note: typename boost::_bi::result_traits<R, F>::type boost::_bi::bind_t<R, F, L>::operator()(A1&) const [with A1 = int, R = int, F = boost::_mfi::mf1<int, Foo, int>, L = boost::_bi::list2<boost::_bi::value<Foo*>, boost::arg<1> >]
Any ideas anyone? Thanks again for your help. Kind regards, Nelis Franken
The problem may be that int and ptrdiff_t are distinct types on your platform.
Try the following:
ptrdiff_t customRand(ptrdiff_t n) { return (rand() % n); }
--Johan Råde
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Nelis Franken wrote:
Any ideas anyone?
The problem is that the temporary object returned by boost::bind doesn't bind to the non-const reference random_shuffle accepts. I'm not sure if there is a nicer solution to using boost::function, as the return type of boost::bind is unspecified. #include <boost/function.hpp> void myShuffle() { boost::function< int (int) > rand = boost::bind(&Foo::customRand, this, _1); random_shuffle(dataVector.begin(), dataVector.end(), rand); } Jens

Thanks Jens! That works great... -----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Jens Theisen Sent: 21 August 2006 10:55 PM To: boost-users@lists.boost.org Subject: Re: [Boost-users] Problem binding a predicate to random_shuffle() Nelis Franken wrote:
Any ideas anyone?
The problem is that the temporary object returned by boost::bind doesn't bind to the non-const reference random_shuffle accepts. I'm not sure if there is a nicer solution to using boost::function, as the return type of boost::bind is unspecified. #include <boost/function.hpp> void myShuffle() { boost::function< int (int) > rand = boost::bind(&Foo::customRand, this, _1); random_shuffle(dataVector.begin(), dataVector.end(), rand); } Jens _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (3)
-
Jens Theisen
-
Johan Råde
-
Nelis Franken