Search code examples
c++pointerstype-conversionfunction-pointersimplicit-conversion

Why is this function call ambiguous though conversion to bool requires an additional step?


Consider the following code:

struct Foo
{
    typedef bool (*fptr_t)(int);

    operator fptr_t() const
    {
        return _func;
    }

    fptr_t _func;
};

class Wrapper
{
public:
    Wrapper(const Foo&) {}
};


void foo(bool b)
{
}

void foo(Wrapper w)
{
}

int main()
{
    Foo f;
    foo(f);
}

Which doesn't compile with an "ambiguous call to overloaded function" error. As I see it, both foo overloads would require a user-defined conversion. However for the Wrapper version, the conversion goes

Foo->(user-defined conversion)Wrapper = exact match

while for the bool version the conversion goes

Foo->(user-defined conversion)fptr_t->(implicit conversion)bool = exact match

which requires an additional step. Furthermore, cppreference states (although I couldn't find the exact paragraph of the standard)

If two conversion sequences are indistinguishable because they have the same rank, the following additional rules apply: 1) Conversion that does not involve pointer to bool or pointer-to-member to bool is better than the one that does.

which also seems to be the case here. So why is this call still ambiguous?


Solution

  • Both conversion sequences are user-defined conversion sequences.

    User-defined conversion sequences that contain different constructors/conversion functions are always considered ambiguous, no matter whether additional standard conversion sequences in the user-defined conversion sequence differ in rank.