Converting an overloaded function is ambiguous

I have a problem when creating a function pointer of an overloaded function leads to a compilation error in g ++ 4.7 and g ++ 4.8, but not in g ++ 4.4, g ++ 4.6 or clang ++ 3.2 (and possibly VS2010).

Having a little understanding, find out if there is a problem with g ++ or with my code, I still can not solve. Are overload resolution rules applicable to converting function pointers other than those that apply to function calls?

This is some minimized code that demonstrates the problem:

template < class T > struct Dummy { typedef T value_type; value_type value; }; template < class T > typename T::value_type f (const T& x) { return x.value; } template < class T > T f (Dummy< T > const& x) { return x.value + 1; } int main (int, char**) { Dummy< int > d = { 1 }; // No ambiguity here d.value = f(d); // This is ambiguous for *some* compilers int (* const f_ptr)(Dummy< int > const&) = f; return f_ptr( d ); } 

clang ++ 3.2, g ++ 4.4 and g ++ 4.6 compile this with -Wall -pedantic --std=c++98 without warning.

g ++ 4.7 and g ++ 4.8, however, give the following error message:

 test.cc: In function 'int main(int, char**)': test.cc:15:45: error: converting overloaded function 'f' to type 'int (* const)(const struct Dummy<int>&)' is ambiguous test.cc:6:18: error: candidates are: typename T::Type f(const T&) [with T = Dummy<int>; typename T::Type = int] test.cc:9:3: error: T f(const Dummy<T>&) [with T = int] 

Is this a problem with newer versions of g ++, or is my code really wrong?

If so, how can this ambiguity be resolved?

+6
source share
1 answer

Is this a problem with newer versions of g ++, or is my code really wrong?

I assume this is a legal code (but I'm not sure). To add to the list: it compiles with clang 3.3 and icc 13.1.3.

how to solve this ambiguity?

you can use

  int (* const f_ptr)(Dummy< int > const&) = f<int>; 

to select the second overload or

  int (* const f_ptr)(Dummy< int > const&) = f<Dummy<int> >; 

to choose the first one.

If you do not want to manually resolve the ambiguity (for example, my suggestion above), I can offer a workaround that uses SFINAE to resolve the ambiguity. I assume that you can use C ++ 11 (the default template arguments for function templates), but I believe that with some additional work, it can be expanded to C ++ 98.

Change the definitions of f to:

 template < class T, class R = typename T::value_type> R f (const T&) { return x.value; } template < class T, class R = T> R f (Dummy< T > const&) { return x.value + 1; } 

In this case, the original line (below) is compiled in gcc (4.7.3 and 4.8.1):

 int (* const f_ptr)(Dummy< int > const&) = f; 
+3
source

Source: https://habr.com/ru/post/957527/


All Articles