Re: Why does "template<typename T> ... function<T(int)>" not match
"int (&)(int)" implicitly?
Steve Hicks wrote:
#include <tr1/functional>
using std::tr1::function;
int foo(int x) { return x+1; }
template <typename T> T bar(function<T(int)> f,int a) { return f(a); }
int main() { return bar(foo,1); }
and I get the error "no matching function for call to =91bar(int (&)
(int), int)". It works if I change bar to take a function<int(int)>.
Right. The difference is that T doesn't have to be deduced anymore.
It also works if I add an explicit cast, as in bar((function<int(int)>)
foo,1).
Right. In this case (the type matches exactly) the compiler is able to
deduce T. You can also write bar<int>(foo,1) -- specifying T so no
deduction has to be performed. You could even write bar<void>(foo,1)
or bar<double>(foo,1) as far as I can tell. So the number of possible
type parameters with successfull template instantiations is even
greater than one. What's the "right" one?
And I know the constructor is implicit, since I can say
"function<int(int)> foo_f = foo; bar(foo_f,1);" and it works just
fine. My code also fails when using a function object (with a member
int operator()(int)).
Right. Because the types don't match. Your function object is not a
std::function and therefore type deduction of T won't work. Type
deduction only considers array-to-pointer, function-to-pointer, cv
qualification, and derived-to-base conversions. Nothing else. No other
implicit conversions. This is a good thing, actually. ;-)
But I'm trying to make a function similar to bind, where you can pass
any sort of function reference/pointer/object/etc without any explicit
casts, and it "just works" (in fact, I'd rather take a function<T(A)>
with both types templated, but one thing at a time...)
You could try to use overloading and SFINAE to "detect the correct T"
for non-function<> objects:
template <typename T>
T bar(function<T(int)> f,int a)
{
... your code ...
}
template <typename Func>
inline typename result_of<Func(int)>::type
bar(Func const& fun, int a)
{
typedef typename result_of<Func(int)>::type ret_t;
return bar<ret_t>(fun,a); // relay
}
The first function template accepts function<T(int)> objects directly
for some T (if T can be deduced or is explicitly given and an implicit
conversion exists. The second function takes any functor, tries to
detect the return type when given an int parameter and relays to the
first function. Wrapping the functor in a function<> object is done
implicitly since the type parameter is specified and doesn't need to
be deduced. -- I havn't tested the code above, though.
I looked at gcc's tr1_impl/functional header and see that function
objects and bind take all sorts of scary-looking variadic templates,
and the entire functor input is a single template _Functor, rather
than an explicit function<T(A)>.
Yeah, why not? If you don't want the code bloat and don't mind the
virtual function call overhead you can always try to wrap the functor
manually in a function<> object like I did above.
But since function<> does have these
implicit constructors, is there any way to help out the compiler in
figuring out what's so obvious to a human?
See above.
Cheers,
SG