The constructor for std::function<...> is a template because it must support any type of input of type of function. There is no single type to try to derive it, so your overloads can be built with; later there will be no compilation that an error has occurred for type mismatch.
You can do it:
GetInfo(item, static_cast<double(*)(ITEM*)>(GetLength));
To explicitly abandon other overloads.
In other words, for the same reason, this will not work:
void foo(int); void foo(void*); struct bar { template <typename T> bar(T f) { f(5); } }; bar b(foo);
Even if the constructor body for bar will only work with void foo(int) , it wants to support any function in which f(5) will work so that the argument type is specified. This allows any function to work in that place, which means that the compiler cannot use one better overload to use.
I think that one solution at the language level is designed so that the overload set is actually a functor. That is, given:
void foo(int); void foo(void*); template <typename T> double foo(int, T);
Naming foo (as in bar(foo) or even just foo(5) ) results in an instance of this type:
struct __foo_overload_set // internal { // forwarders void operator()(int __arg0) const { // where __foo0 is the zeroth overload, etc... return __foo0(__arg0); } void operator()(void* __arg0) const { return __foo1(__arg0); } template <typename __Arg1> double operator()(int __arg0, __Arg1&& __arg1) const { return __foo2(__arg0, std::forward<__Arg1>(__arg1)); } // converters typedef void(*__foo0_type)(int); operator __foo0_type() const { return __foo0; } typedef void(*__foo1_type)(void*); operator __foo1_type() const { return __foo1; } template <typename T> struct __foo2_type { typedef void(*type)(int, T); }; template <typename T> operator typename __foo2_type<T>::type() const { return __foo2; } };
Which, being itself called, will compile in the context we need. (AFAIK, it does not introduce any ambiguities that do not yet exist, although they are completely untested.)