Reputation: 301
I have a helper method that takes as input a boost::function<>
type object and wraps the function with another functor that handles some other logistics.
Here is what my signature looks like:
class Example {
public:
typedef ... Callback;
...
template<typename T>
static Callback make_wrapper( const boost::function<void( T )>& );
};
If I try to pass make_wrapper the result of calling boost::bind
inline I get compilation errors about types being incompatible (Apple LLVM version 7.3.0)
class OtherClass {
public:
void method ( uint32_t );
};
OtherClass* other;
Example::Callback c = Example::make_wrapper ( boost::bind( &OtherClass::method, other, _1 ) );
this gives:
error: no matching function for call to 'make_wrapper'
note: candidate template ignored: could not match 'function' against 'bind_t'
I have found 2 ways around this:
Temp variable:
boost::function<void( uint32_t )> f = boost::bind( &OtherClass::method, other, _1 );
Example::Callback c = Example::make_wrapper ( f );
Call specific specialization of make_wrapper:
Example::Callback c = Example::make_wrapper<uint32_t> ( boost::bind( &OtherClass::method, other, _1 ) );
I would much prefer it if I could skip the extra hinting and call make_wrapper with the inline call to bind.
Is there a way that I can declare the signature of the make_wrapper template to help the compiler figure out the type without needing to use one of workarounds above?
Upvotes: 1
Views: 177
Reputation: 13988
Whenever you use bind
you discard all information about the bound function's parameter types. A function template can't possibly deduce the parameter type T
, because the return value of bind
is a function object that can be called with any number of parameters of any types.
You could wrap the bind
function into helper function template to deduce the bound member function and especially its result type and parameters (example uses std::bind
and std::function
but I believe it can be easily transformed to boost
):
#include <iostream>
#include <string>
#include <functional>
struct foo {
void bar(int a, std::string s) {
std::cout << a << " " << s << std::endl;
}
};
template<typename T1, typename T2>
void make_wrapper(const std::function<void( T1, T2 )>&) {
}
template <class Foo, class Res, class... Args, class... Placeholders>
std::function<Res(Args...)> my_bind(Res (Foo::*bar)(Args...), Foo& f, Placeholders... ps) {
return std::bind(bar, f, ps...);
}
int main() {
foo f;
make_wrapper(my_bind(&foo::bar, f, std::placeholders::_1, std::placeholders::_2));
}
The code will work as long as foo::bar
is not overloaded in which case you can't avoid static_cast
.
Upvotes: 1
Reputation: 16421
Both std::bind
and boost::bind
list the return type as unspecified. This means you simply cannot know that, if you want to be at all portable.
Upvotes: 0