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