where F is `int(int, int)` in my question so the concrete form of the constructor is `function( int (&& f)(int,int) );`
However, the following (correct) code shows that my first thought is incorrect:
1 2 3 4 5
int add(int i, int j) { return i + j; }
std::string add(const std::string& s1, const std::string& s2) { return s1 + s2; }
void test_func(int (&&f)(int,int)) { f(1,2); }
...
test_func(add);
The C++ compiler I use correctly selects the first `add` function to match the testing function with `int (&& f)(int,int)` parameter where the testing function acts as the constructor of `std::function` class.
From the above example, I think the compiler should be able to pick the first `add` function. But why the error when I tried to assign an overloaded function to a `std::function<int(int, int)>` variable in which the type of the function has already been clearly specified?
There is a constructor template and a class template in play here, and the <int(int, int)> in std::function<int(int, int)> xxx = add; is attached to the class template, not the constructor template.
To illustrate, this code exhibits the same problem:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
void f(int) {}
void f(float) {}
template <int N>
struct my_class_template
{
template <typename F>
my_class_template(F&&) {}
};
int main()
{
// Attempt to call my_class_template<42>::my_class_template:
my_class_template<42> o(f); // error:
// There is no way to determine which version of f is intended.
// The "42" attaches to the class template's template parameter, not the
// constructor template's template parameter.
}
There is no way to explicitly specify the template arguments of a constructor template.
In your case, you can work-around this limitation by adding a static_cast around the function name: std::function<int(int, int)> xxx = static_cast<int(*)(int, int)>(add);
Alternatively you can use a lambda expression as follows: std::function<int(int, int)> xxx = [](int a, int b) { return add(a, b); };