8

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?

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
Evan Teran
  • 87,561
  • 32
  • 179
  • 238

1 Answers1

4

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;
}
Node
  • 3,443
  • 16
  • 18
  • 1
    Hmm, I think I follow. The compiler is attempting both the 2 template argument version `(Arg,Ret)` and the 3 argument version `(Arg,Arg,Ret)` and is trying to match my `` as the 2 `Arg`s and attempting to deduce the `Ret`? – Evan Teran Jul 11 '11 at 21:06
  • @Evan - yeah, that's what I was trying to say. – Node Jul 11 '11 at 21:07