最近バグを修正しました。
次のコードでは、オーバーロードされた関数の1つがconstで、もう1つはそうではありませんでした。この問題は、両方の関数をconstにすることで修正されます。
私の質問は、コンパイラーがパラメーターが0のときにのみ不平を言った理由です。
#include <iostream>
#include <string>
class CppSyntaxA
{
public:
void f(int i = 0) const { i++; }
void f(const std::string&){}
};
int main()
{
CppSyntaxA a;
a.f(1); // OK
//a.f(0); //error C2666: 'CppSyntaxA::f': 2 overloads have similar conversions
return 0;
}
_0
_はC++では特別です。 nullポインターの値は_0
_であるため、C++では_0
_をポインター型に変換できます。つまり、あなたが電話したとき
_a.f(0);
_
_0
_の値でint
を指定してvoid f(int i = 0) const
を呼び出すか、_char*
_をnullに初期化してvoid f(const std::string&)
を呼び出すことができます。
通常、int
バージョンは完全に一致するのでより良いでしょうが、この場合int
バージョンはconst
なので、「変換」する必要がありますa
_const CppSyntaxA
_に変換します。ここで、_std::string
_バージョンはそのような変換を必要としませんが、_char*
_への変換とその後の_std::string
_への変換が必要です。これは、どちらの場合も、変換が等しいと見なすのに十分であると見なされ、あいまいです。両方の関数をconst
または非const
にすることで問題が修正され、int
オーバーロードが選択されます。
私の質問は、コンパイラーがパラメーターが0のときにのみ不平を言った理由です。
0は整数リテラルであるだけでなく、nullポインタリテラルでもあるからです。 1はnullポインターリテラルではないため、あいまいさはありません。
あいまいさは、文字へのポインターを引数として受け入れるstd::string
の暗黙的な変換コンストラクターから発生します。
さて、intからintへのID変換は、ポインタから文字列への変換よりも優先されますが、変換を含む別の引数があります。暗黙のオブジェクト引数です。 1つのケースでは、変換はCppSyntaxA&
からCppSyntaxA&
への変換であり、別のケースではCppSyntaxA&
からconst CppSyntaxA&
への変換です。
したがって、1つの引数のために1つのオーバーロードが優先され、別の引数のためにもう1つのオーバーロードが優先されます。したがって、明確に優先されるオーバーロードはありません。
この問題は、両方の関数をconstにすることで修正されます。
両方のオーバーロードがconst
修飾されている場合、暗黙のオブジェクト引数変換シーケンスは同一であるため、オーバーロードの1つが明白に優先されます。