I just write an simple example to test boost::bind. I use it to instantiate a template member function, but it won't compile with g++ 4.6.0. I don't know what's the problem. Here's the code:
#include <boost/bind.hpp>
struct Functor
{
void operator()()
{
}
};
struct DerivedFinishAction
{
DerivedFinishAction()
{}
void Inc()
{
}
template <typename T>
void TmplFunc(T t)
{
(boost::bind(&DerivedFinishAction::BindFunc<T>, this , t))();
}
template <typename T>
void BindFunc(T t)
{
t();
}
void Func()
{
Functor f;
TmplFunc(f); // this is OK
TmplFunc(boost::bind(&DerivedFinishAction::Inc, this)); // compile error
}
};
int main(int argc, char *argv[])
{
return 0;
}
And g++ gives the following errors:
In file included from /usr/include/boost/bind.hpp:22:0,
from testBind.cpp:1:
/usr/include/boost/bind/bind.hpp: In member function ‘void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = boost::_mfi::mf1<void, DerivedFinishAction, boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > > >, A = boost::_bi::list0, A1 = boost::_bi::value<DerivedFinishAction*>, A2 = boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > >]’:
/usr/include/boost/bind/bind_template.hpp:20:59: instantiated from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()() [with R = void, F = boost::_mfi::mf1<void, DerivedFinishAction, boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > > >, L = boost::_bi::list2<boost::_bi::value<DerivedFinishAction*>, boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > > >, boost::_bi::bind_t<R, F, L>::result_type = void]’
testBind.cpp:24:5: instantiated from ‘void DerivedFinishAction::TmplFunc(T) [with T = boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > >]’
testBind.cpp:37:58: instantiated from here
/usr/include/boost/bind/bind.hpp:313:9: error: invalid use of void expression
Can anybody help explain this? Why the first instantiation is OK while the second one causes compile error?
There's a (non-obvious) feature of boost::bind involved here. http://www.boost.org/libs/bind/#nested_binds
If you write:
void func1(int len) {return len+1;};
int func2(std::string str) {return str.length();};
assert(
boost::bind(func1, boost::bind(func2, _1) )("Hello")
== 6 );
boost::bind assumes that what you meant is "run func2 on "Hello", then run func1 on the result". This allows more interesting partial function application.
In your program, you have an expression which amounts to:
boost::bind(&DerivedFinishAction::BindFunc<...>,
this,
boost::bind(&DerivedFinishAction::Inc, this))
So boost::bind tries to figure out how to run DerivedFinishAction::Inc on it arguments, so it can pass that result into DerivedFinishAction::BindFunc<...>. But DerivedFinishAction::Inc returns void, which cannot be passed into DerivedFinishAction::BindFunc<...>. Thus you get a compiler error:
/usr/include/boost/bind/bind.hpp:313:9: error: invalid use of void expression
Edit: Per the documentation, you can use protect to achieve your desired behavior:
#include <boost/bind/protect.hpp>
...
TmplFunc(boost::protect(boost::bind(&DerivedFinishedAction::Inc, this))); // no longer an error
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With