Partager via


Erreur du compilateur C2666

'identifier' : les surcharges de nombre ont des conversions similaires

Une fonction ou un opérateur surchargé est ambigu. Les listes de paramètres formels peuvent être trop similaires pour que le compilateur résolve l’ambiguïté. Pour résoudre cette erreur, cassez explicitement un ou plusieurs des paramètres réels.

Exemples

L’exemple suivant génère l’erreur C2666 :

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

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

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

Cette erreur peut être générée suite au travail de conformité du compilateur effectué pour Visual Studio 2019 version 16.1 :

  • Une conversion qui promeut une énumération dont le type sous-jacent est fixe à son type sous-jacent est meilleure qu’une conversion qui promeut au type sous-jacent promu, si les deux diffèrent.

L’exemple suivant montre comment le comportement du compilateur change dans Visual Studio 2019 version 16.1 et versions ultérieures :

#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{});
}

Cette erreur peut également être générée suite au travail de conformité du compilateur effectué pour Visual Studio .NET 2003 :

  • opérateurs binaires et conversions définies par l’utilisateur en types de pointeur

  • la conversion de qualification n’est pas la même que la conversion d’identité

Pour les opérateurs binaires <, , >= <et >=, un paramètre passé est désormais converti implicitement en type d’opérande si le type du paramètre définit un opérateur de conversion défini par l’utilisateur pour convertir en type d’opérande. Il y a maintenant un potentiel d’ambiguïté.

Pour le code valide dans les versions Visual Studio .NET 2003 et Visual Studio .NET de Visual C++, appelez explicitement l’opérateur de classe à l’aide de la syntaxe de fonction.

// 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");
}

L’exemple suivant génère l’erreur 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);
    }
};