I am trying to understand why std::function is not able to distinguish between overloaded functions.
#include <functional>
void add(int,int){}
class A {};
void add (A, A){}
int main(){
        std::function <void(int, int)> func = add;
}
In the code shown above, function<void(int, int)> can match only one of these functions and yet it fails. Why is this so? I know I can work around this by using a lambda or a function pointer to the actual function and then storing the function pointer in function. But why does this fail? Isn't the context clear on which function I want to be chosen? Please help me understand why this fails as I am not able to understand why template matching fails in this case.
The compiler errors that I get on clang for this are as follows:
test.cpp:10:33: error: no viable conversion from '<overloaded function type>' to
      'std::function<void (int, int)>'
        std::function <void(int, int)> func = add;
                                       ^      ~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_03:1266:31: note: 
      candidate constructor not viable: no overload of 'add' matching
      'std::__1::nullptr_t' for 1st argument
    _LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {}
                              ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_03:1267:5: note: 
      candidate constructor not viable: no overload of 'add' matching 'const
      std::__1::function<void (int, int)> &' for 1st argument
    function(const function&);
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_03:1269:7: note: 
      candidate template ignored: couldn't infer template argument '_Fp'
      function(_Fp,
      ^
1 error generated.
EDIT - In addition to MSalters' answer, I did some searching on this forum and found the exact reason why this fails. I got the answer from Nawaz's reply in this post.
I have copy pasted from his answer here:
    int test(const std::string&) {
        return 0;
    }
    int test(const std::string*) {
        return 0;
    }
    typedef int (*funtype)(const std::string&);
    funtype fun = test; //no cast required now!
    std::function<int(const std::string&)> func = fun; //no cast!
So why std::function<int(const std::string&)> does not work the way funtype fun = test works above?
Well the answer is, because std::function can be initialized with any object, as its constructor is templatized which is independent of the template argument you passed to std::function.
 
     
     
     
     
     
     
    