オーバーロードの解決では、2 つの同等に実行可能な関数 (両方ともユーザー定義の変換がある) から選択する必要があるため、エラーが発生しました。関数オーバーロードの解決は非常に複雑な問題です。過負荷解決の詳細については、Stephan T. Lavavej による最近の講義などを参照してください。通常、単一引数のコンストラクターを作成explicit
してから、明示的なコンストラクター引数を使用して関数を呼び出すのが最善です。
test(0L)
オーバーロードがないため、オーバーロードと完全に一致しませんtest(long)
。あなたが提供した 2 つのオーバーロードはどちらも、引数にユーザー定義の変換がありますが、コンパイラはそれらを同等に実行可能と見なします。オーバーA
ロードでは、標準の変換 (long から int へ) の後にユーザー定義の変換 (int から A へ) を実行し、B
オーバーロードではユーザー定義の変換 (long から B へ) を実行する必要があります。ただし、どちらもユーザー定義の暗黙的な変換シーケンスです。
これらはどのようにランク付けされていますか?標準では、13.3.3.2 ランキングの暗黙的な変換シーケンス [over.ics.rank]で述べられています。
S1 が S2 の適切なサブシーケンスである場合、標準変換シーケンス S1 は標準変換シーケンス S2 よりも優れた変換シーケンスです。
これらのタイプのタイブレークは、たとえば、A が B から派生したクラスである場合 (またはその逆) に適用されます。しかし、ここではどちらの変換シーケンスも他方のサブシーケンスではありません。したがって、それらは等しく実行可能であり、コンパイラは呼び出しを解決できません。
class A
{
public:
explicit A(int){}
A(){}
};
class B: public A
{
public:
explicit B(long){}
B(){}
};
void test(A a)
{}
void test(B b)
{}
int main()
{
test(A(0L)); // call first overload
test(B(0L)); // call second overload
return 0;
}
注:int main()
ではなく、void main()
です。