Implicit conversions with std::function [duplicate]
Possible Duplicates:
Why can't my C++ compiler deduce template argument for boost function? Isn't the template argument (the signature) of std::function part of its type?
I have the following:
#include <functional>
void Foo( std::function<void()> );
void Foo( std::function<void(开发者_运维百科int)> );
void Bar();
int main()
{
Foo( Bar ); // Error: ambiguous
Foo( [](){} ); // Error: ambiguous
Foo( std::function<void()>( Bar ) ); // Ok
Foo( std::function<void()>( [](){} ) ); // Ok
}
Can I make the first two lines in main() work without the function-style cast in the last two lines? Perhaps with a std::enable_if solution?
Any call to Foo with a parameter which is not exactly one of std::function<void()>
and std::function<void(int)>
will result in an unresolved overloading. Even silly things like Foo(1)
or Foo("abc")
. This is because constructors of std::function
are templated and accept any type. std::function<void()>(1)
would fail at instantiation, but overload resolution happens before instantiation.
So no, you need to provide an exact match to one of the functions, one way or another. You may introduce other overloaded instances of Foo, like
void Foo(void (*)());
void Foo(void (*)(int));
and this will result in a better match and the ambiguity will be no more.
It is possible to use SFINAE to make this work correctly, in C++0x. However, MSVC's SFINAE bugs make it impossible for them, as far as I know, and GCC's library implementers don't seem to have noticed, so this unfortunately doesn't work.
You could also try some sort of make_function
, I guess. Excuse my variadic templates, it's been a while.
template<typename T> struct function_proxy {
T f;
template<typename Ret, typename... T> operator std::enable_if<std::is_same<Ret, decltype(f(std::declval<T>()...))>::value, std::function<Ret(T...)>>::type () {
return std::function<Ret(T...)>(f);
}
};
template<typename T> function_proxy<T> make_function(T&& t) {
return function_proxy { std::forward<T>(t); }
}
精彩评论