Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why does ptr_fun find this ambiguous even when template parameters are given?

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?

like image 985
Evan Teran Avatar asked Jul 11 '11 20:07

Evan Teran


1 Answers

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;
}
like image 52
Node Avatar answered Nov 05 '22 14:11

Node