Error del compilador C2666

'identificador': número sobrecargas tienen conversiones similares

Una función o un operador sobrecargados son ambiguos. Las listas de parámetros formales pueden ser demasiado similares para que el compilador resuelva la ambigüedad. Para resolver este error, convierta explícitamente uno o varios de los parámetros reales.

Ejemplos

El ejemplo siguiente genera el error C2666:

// C2666.cpp
struct complex {
   complex(double);
};

void h(int,complex);
void h(double, double);

int main() {
   h(3,4);   // C2666
}

Este error puede deberse a una operación de conformidad del compilador para la versión 16.1 de Visual Studio 2019:

  • Una conversión que promueve una enumeración cuyo tipo subyacente se fija en su tipo subyacente es mejor que una que promueve al tipo subyacente promocionado, si son diferentes.

En el ejemplo siguiente, se muestra cómo cambia el comportamiento del compilador en la versión 16.1 de Visual Studio 2019 y versiones posteriores:

#include <type_traits>

enum E : unsigned char { e };

int f(unsigned int)
{
    return 1;
}

int f(unsigned char)
{
    return 2;
}

struct A {};
struct B : public A {};

int f(unsigned int, const B&)
{
    return 3;
}

int f(unsigned char, const A&)
{
    return 4;
}

int main()
{
    // Calls f(unsigned char) in 16.1 and later. Called f(unsigned int) in earlier versions.
    // The conversion from 'E' to the fixed underlying type 'unsigned char' is better than the
    // conversion from 'E' to the promoted type 'unsigned int'.
    f(e);
  
    // Error C2666. This call is ambiguous, but previously called f(unsigned int, const B&). 
    f(e, B{});
}

Este error también puede deberse a una operación de conformidad del compilador para Visual Studio .NET 2003:

  • Operadores binarios y conversiones definidas por el usuario a tipos de puntero.

  • La conversión de calificación no es la misma que la conversión de identidad.

Para los operadores binarios <, >, <= y >=, un parámetro pasado se convierte ahora implícitamente en el tipo del operando si el tipo del parámetro define un operador de conversión definida por el usuario para convertir al tipo del operando. Ahora existe la posibilidad de ambigüedad.

Para el código que es válido en las versiones de Visual C++ de Visual Studio .NET 2003 y Visual Studio .NET, llame al operador de clase explícitamente usando la sintaxis de función.

// C2666b.cpp
#include <string.h>
#include <stdio.h>

struct T
{
    T( const T& copy )
    {
        m_str = copy.m_str;
    }

    T( const char* str )
    {
        int iSize = (strlen( str )+ 1);
        m_str = new char[ iSize ];
        if (m_str)
            strcpy_s( m_str, iSize, str );
    }

    bool operator<( const T& RHS )
    {
        return m_str < RHS.m_str;
    }

    operator char*() const
    {
        return m_str;
    }

    char* m_str;
};

int main()
{
    T str1( "ABCD" );
    const char* str2 = "DEFG";

    // Error - Ambiguous call to operator<()
    // Trying to convert str1 to char* and then call
    // operator<( const char*, const char* )?
    //  OR
    // trying to convert str2 to T and then call
    // T::operator<( const T& )?

    if( str1 < str2 )   // C2666

    if ( str1.operator < ( str2 ) )   // Treat str2 as type T
        printf_s("str1.operator < ( str2 )\n");

    if ( str1.operator char*() < str2 )   // Treat str1 as type char*
        printf_s("str1.operator char*() < str2\n");
}

El ejemplo siguiente genera el error C2666.

// C2666c.cpp
// compile with: /c

enum E
{
    E_A,   E_B
};

class A
{
    int h(const E e) const {return 0; }
    int h(const int i) { return 1; }
    // Uncomment the following line to resolve.
    // int h(const E e) { return 0; }

    void Test()
    {
        h(E_A);   // C2666
        h((const int) E_A);
        h((int) E_A);
    }
};