So, here is some basic code which illustrates my question:
#include <functional>
int func(int x) {
return x;
}
int func(int x, int y) {
return x + y;
}
int main() {
std::ptr_fun<int, int>(func);
}
We have 2 overloads for a function with a different number of parameters. Then I attempt to turn the single parameter version in a functor. Of course, I am met with the following error:
test.cc: In function 'int main()': test.cc:13:29: error: call of overloaded 'ptr_fun()' is ambiguous /usr/lib/gcc/x86_64-pc-linux-gnu/4.5.2/include/g++-v4/bits/stl_function.h:437:5: note: candidates are: std::pointer_to_unary_function std::ptr_fun(_Result (*)(_Arg)) [with _Arg = int, _Result = int] /usr/lib/gcc/x86_64-pc-linux-gnu/4.5.2/include/g++-v4/bits/stl_function.h:463:5: note: 开发者_开发技巧 std::pointer_to_binary_function std::ptr_fun(_Result (*)(_Arg1, _Arg2)) [with _Arg1 = int, _Arg2 = int, _Result = int]
I know I could just cast func
and be done with it, but it got me thinking why is this ambiguous? Neither version of std::ptr_fun
have default parameters in the template definitions, and I have explicitly said that the two template parameters are int
.
In fact, if I just do what the compiler is essentially doing during template instantiation time like this:
#include <functional>
int func(int x) {
return x;
}
int func(int x, int y) {
return x + y;
}
std::pointer_to_unary_function<int,int> my_ptr_fun (int (*f)(int)) {
return std::pointer_to_unary_function<int,int>(f);
}
int main() {
my_ptr_fun(func);
}
It compiles just fine, somehow the ambiguity is gone! Anyone have any insite into why this is the case?
Its because when you call a templated function, you don't have to specify any template parameters that can be inferred by the type of the function arguments. As a result, calling std::ptr_fun<int, int>
doesn't actually specify which of the std::ptr_fun
overloads you calling, and it relies on the function you pass as an argument for resolution. As your func
has overloads that fit for both std::ptr_fun
overloads, there is ambiguity.
Edit: Here is an example to demonstrate my point - ran on Ideone, it shows both function calls return the same type.
#include <functional>
#include <iostream>
#include <typeinfo>
double func(int x)
{
return x;
}
int main()
{
std::cout << typeid(std::ptr_fun<int>(func)).name() << std::endl;
std::cout << typeid(std::ptr_fun<int, double>(func)).name() << std::endl;
}
精彩评论