Strange Ambiguous Call to Overloaded Function Error

C++ strange ambiguous call to overloaded function

'void a(foo)' [found using argument-dependent lookup]

Well, surprisingly MSVC has a very good error explanation:

Following the standard, inside a function the compiler look for symbols in the current namespace and in the namespace where the type of the arguments are defined.

In the first case a is in foobar and in the namespace of the argument type foo: the global namespace, making it ambiguous.

In the second case a is in foobar but not in the namespace of the argument type bar::foo: with is bar.

Strange ambiguous call to overloaded function error

Look at the error message from gcc:

a.cpp:16: error: call of overloaded ‘function(double, double)’ is ambiguous
a.cpp:3: note: candidates are: void function(int, int)
a.cpp:9: note: void function(float, float)

A call to either function would require truncation, which is why neither is preferred over the other. I suspect you really want void function(double y,double w). Remember that in C/C++, the default floating-point type for literals and parameter passing is double, NOT float.

UPDATE

If you really don't want to change the function signature from float to double, you can always use literals that are typed as float. If you add the suffix f to the floating point numbers, they will be typed float.

Your examples would then be function(1.2f, 2f) and function(1, 2.2f).

fpclassify': ambiguous call to overloaded function

The error message like fpclassify': ambiguous call to overloaded function is always accompanied by notes. For example, for a simple program

#include <cmath>
int main() {
std::isnan(5);
}

VS complains:

corecrt_math.h(415): error C2668: 'fpclassify': ambiguous call to overloaded function
corecrt_math.h(300): note: could be 'int fpclassify(long double) throw()'
corecrt_math.h(295): note: or 'int fpclassify(double) throw()'
corecrt_math.h(290): note: or 'int fpclassify(float) throw()'
corecrt_math.h(415): note: while trying to match the argument list '(_Ty)'
with [ _Ty=int ]
<source>(3): note: see reference to function template instantiation 'bool isnan<int>(_Ty) throw()' being compiled
with [ _Ty=int ]

From these notes we can infer that _Ty is int and that std::nan was called on the line 3 of our source code. Take a look at the full compiler output for your compilation, it will tell you the exact place in your code where the error is triggered.

Error: ambiguous call to overloaded function

You can press F12 on that function.

Update

Based on comments from the OP, the problem was due to a definition of acos being brought in from G3D::. Using std::acos as opposed to acos will remove the ambiguity.

Why does this program in c++, visual studio code shows error

Type area(5.5f) to force the value to be a float.

The compiler does not know if it should cast your double value to an int or a float. Therefore, it is ambiguous.

MSVC - C2668 ambiguous call to overloaded function - Is it a compiler bug?

For the call Foo<int>() the compiler can deduce Foo<int>() for the first template, and Foo<int>(void) for the second.

From temp.deduct.partial#11:

... if G has a trailing function parameter pack for which F does not have a corresponding parameter, and if F does not have a trailing function parameter pack, then F is more specialized than G.

This is a tie breaker, and the first template is selected.

Not being able to resolve the ambiguity appears to be a MSVC bug.

c++ templates and ambiguous call to overloaded function

This looks like a bug in MSVC and GCC. The call should resolve to the second overload (Clang and EDG are doing that).

For the call B::func(g, dt, bx), name lookup finds the two func templates. Template argument deduction and substitution is performed on each of them in order to generate function template specialization declarations that can subsequently participate in overload resolution. Deduction succeeds for both templates and we're left with two specializations:

void B::func<BX, int, G<BX<int>, int>>(const G<BX<int>, int>&, const DT<BX, int>*, BX<int>&);
void B::func<BX, int, int> (const G<BX<int>, int>&, const DT<BX, int>*, BX<int>&);

The two functions have identical parameter declaration clauses, so clearly overload resolution cannot distinguish between them based on conversions from the arguments of the call; it has to resort to the last two steps in the process.

First, if one of the functions is a template specialization and the other one is not, the non-template one is preferred; not applicable here.

Last, it looks at the templates from which the two specialization declarations were synthesized; if one of the templates is more specialized than the other according to the partial ordering of function templates, then the corresponding specialization is preferred. (This is the only place in the process where the original templates come back into play.)

The description below is not very accurate and skips quite a few details, but I'm trying to concentrate on the parts that are relevant to this case. Very roughly:

  • First, references and cv-qualifiers are stripped from the function parameter declarations of both templates, yielding:

    F1(M          , const DT<T1, T>*, T1<T>)
    F2(G<T2<U>, V>, const DT<T2, U>*, T2<U>)

    (template parameter names changed to avoid confusion)

  • Then, deduction is attempted as if for a call to one template using the forms of the function parameters of the other template as arguments, and then the other way around. In this case, the last two pairs of corresponding parameters have identical forms, so deduction succeeds both ways. For the first pair of corresponding parameters:

    • Deducing M from an argument of the form G<T2<U>, V> works; M is deduced as G<T2<U>, V>.
    • Deducing T2, U and V in G<T2<U>, V> from an argument of the form M doesn't work (M can be anything).

    In other words, G<T2<U>, V> is a "more specific" form than M; it cannot represent all the types that M can represent; this is the intuitive meaning that more specialized is trying to formalize in this context.

  • So, deduction works for all pairs of corresponding parameters from F2 to F1, but not the other way around. This makes F2 more specialized than F1 in terms of partial ordering.

This means that the specialization corresponding to the second template is preferred in overload resolution.



Related Topics



Leave a reply



Submit