Why might my compiler see the following GetLength function pointer as ambiguous
pseudo-code:
size_t GetLength(char*);
size_t GetLength(wchar_t*);
struct ITEM { };
double GetLength(ITEM*);
CString GetInfo(ITEM * item, std::function<double (ITEM*)> fn)
{
... omitted for clarity
}
ITEM * item = new ITEM;
cout << GetInfo(item, GetLength); // <- ambiguous error
GetInfo only allows something of the double return + ITEM* argument pattern. So why is it considering (and not discarding) the two string based variations of GetLength?
The constructor for
std::function<...>is templated because it has to be able to support any function-like input type. There’s no single type to try to deduce to, so your overloads are all possible to construct with; it wouldn’t be until later into compilation later that an error arose for a type mismatch.You could do this:
To explicitly discard the other overloads.
In other words, it’s the same reason this won’t work:
Even though the constructor body for
barwill only work withvoid foo(int),it wants to support any function where
f(5)will work so the argument type is templated. This allows any function to work in that place, which means the compiler cannot deduce a single best overload to use.I think that one language-level solution is for an overload set to actually be a functor itself. That is, given:
Naming
foo(as inbar(foo)or even justfoo(5)) results in an instance of this type:Which, being callable itself, will compile in the context we want. (AFAIK, it does not introduce any ambiguities that don’t already exist, though it’s completely untested.)