I came across a bug with the binders. Had heard from people that the standard ones are not very effective and buggy and boost binders should be used. But I realized it recently why that's said.
Here is a piece of code that should work but does not, why? Because STL bind2nd works with const member functions and NOT the non-const member functions. The code first:
[CODE]
size_t N = 1000;
vector<vector<int> > v(N);
for_each(v.begin(), v.end(), bind2nd(mem_fun_ref(&vector<int>::reserve)),N));
Another sample to test:
[CODE]
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;
struct Test
{
void func1(int){}
void func2(int)const{}
};
int main()
{
size_t N=100;
vector<Test> TestVectorObject(N);
for_each(TestVectorObject.begin(), TestVectorObject.end(), bind2nd(mem_fun_ref(&Test::func1),N)); //ERROR
for_each(TestVectorObject.begin(), TestVectorObject.end(), bind2nd(mem_fun_ref(&Test::func2),N)); //OK
}
Try compiling with online Comeau here - Online Comeau Compiler and see for yourself. The above code will compile fine but just comment the const version and uncomment the non-const version and see. The code will fail to compile.
So, what's the solution? Two possible solutions come to my mind. The first would need you to write a functor whose operator() takes each object of the vector and calls the required member function. The other is to use tr1::bind.
Here are the relevant codes for the two solutions that I talked about.
Solution (using explicit functor)
[CODE]
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;
template<typename T>
struct CallNonConstFunc1
{
void operator() (T& obj) const
{
obj.func1(int());
}
};
struct Test
{
void func1(int){}
void func2(int)const{}
};
int main()
{
size_t N=100;
vector<Test> TestVectorObject(N);
//for_each(TestVectorObject.begin(), TestVectorObject.end(), bind2nd(mem_fun_ref(&Test::func1),N));
for_each(TestVectorObject.begin(), TestVectorObject.end(), CallNonConstFunc1<Test>());
for_each(TestVectorObject.begin(), TestVectorObject.end(), bind2nd(mem_fun_ref(&Test::func2),N));
}
Not very elegant, isn't it? So, lets see how tr1::bind does it...
Solution (using tr1::bind)
[CODE]
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;
using namespace std::tr1;
using namespace std::tr1::placeholders;
template<typename T>
struct CallNonConstFunc1
{
void operator() (T& obj) const
{
obj.func1(int());
}
};
struct Test
{
void func1(int){}
void func2(int)const{}
};
int main()
{
size_t N=100;
vector<Test> TestVectorObject(N);
for_each(TestVectorObject.begin(), TestVectorObject.end(), bind(mem_fun_ref(&Test::func1),_1,N));
for_each(TestVectorObject.begin(), TestVectorObject.end(), CallNonConstFunc1<Test>());
for_each(TestVectorObject.begin(), TestVectorObject.end(), bind2nd(mem_fun_ref(&Test::func2),N));
}
Try compiling that correction with Dinkumware online compiler here - Dinkumware Exam (online compiler)
References:
-- Scott Meyers : tr1 Information - TR1 Information - Scott Meyers
-- Dinkumware : tr1 - Dinkumware TR1 Documentation
-- Pete Becker : C++ Function Objects in TR1 - C++ Function Objects in TR1 - Pete Becker
Have fun!
Friday, February 02, 2007
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment