Compilerfehler C2666

"Bezeichner": Nummernüberladungen weisen ähnliche Konvertierungen auf

Eine überladene Funktion oder ein Überlastungsoperator ist mehrdeutig. Formale Parameterlisten sind möglicherweise zu ähnlich, damit der Compiler die Mehrdeutigkeit auflösen kann. Um diesen Fehler zu beheben, wandeln Sie einen oder mehrere der tatsächlichen Parameter explizit um.

Beispiele

Im folgenden Beispiel wird C2666 generiert:

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

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

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

Dieser Fehler kann aufgrund der Compilerkonformität generiert werden, die für Visual Studio 2019, Version 16.1, durchgeführt wurde:

  • Eine Konvertierung, die eine Enumeration, deren zugrunde liegender Typ fest ist, in ihren zugrunde liegenden Typ höherstuft, ist besser als eine Konvertierung, die in den höhergestuften zugrunde liegenden Typ höherstuft, wenn die beiden Typen unterschiedlich sind.

Im folgenden Beispiel wird veranschaulicht, wie sich das Compilerverhalten in Visual Studio 2019, Version 16.1 und höher, ändert:

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

Dieser Fehler kann auch als Ergebnis der Compilerkonformität generiert werden, die für Visual Studio .NET 2003 ausgeführt wurde:

  • binäre Operatoren und benutzerdefinierte Konvertierungen in Zeigertypen

  • Die Qualifizierungskonvertierung ist nicht mit der Identitätskonvertierung identisch.

Für die binären Operatoren <, =><und >=, wird nun ein übergebener Parameter implizit in den Typ des Operanden konvertiert, wenn der Typ des Parameters einen benutzerdefinierten Konvertierungsoperator definiert, der in den Typ des Operanden konvertiert werden soll. Es besteht nun das Potenzial für Mehrdeutigkeit.

Rufen Sie für Code, der sowohl in visual Studio .NET 2003- als auch in Visual Studio .NET-Versionen von Visual C++ gültig ist, den Klassenoperator explizit mithilfe der Funktionssyntax auf.

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

Im folgenden Beispiel wird C2666 generiert.

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