コンパイラ エラー C2666

'identifier': number のオーバーロードは、同様の変換を行います

オーバーロードされた関数または演算子はあいまいです。 仮パラメーター リストは類似しすぎているため、コンパイラであいまいさを解決できない可能性があります。 このエラーを解決するには、1 つ以上の実際のパラメーターを明示的にキャストします。

次の例では C2666 が生成されます。

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

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

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

このエラーは、Visual Studio 2019 バージョン 16.1 で実行されたコンパイラの準拠作業の結果として生成される可能性があります。

  • 基になる型が固定されている列挙型は、その基になる型に昇格させる変換の方が、2 つが異なる場合、昇格される基になる型に昇格させる変換よりも優先されます。

次の例は、Visual Studio 2019 の 16.1 以降のバージョンでコンパイラの動作がどのように変更されるかを示しています。

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

このエラーは、Visual Studio .NET 2003 で実行されたコンパイラの準拠作業の結果として生成される可能性もあります。

  • 二項演算子とユーザー定義のポインター型への変換

  • 限定変換は ID 変換と同じではありません

2 項演算子 <、>、<=、および >= では、パラメーターの型がオペランドの型に変換するためのユーザー定義の変換演算子を定義している場合、渡されたパラメーターは暗黙的にオペランドの型に変換されるようになりました。 それで、あいまいさが生じる可能性があります。

Visual Studio .NET 2003 バージョンと Visual Studio .NET バージョンの Visual C++ の両方で有効なコードの場合は、関数構文を使用してクラス演算子を明示的に呼び出します。

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

次の例では 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);
    }
};