今日、オーバーロード解決のかなり奇妙なケースに遭遇しました。私はそれを次のように減らしました:
struct S
{
S(int, int = 0);
};
class C
{
public:
template <typename... Args>
C(S, Args... args);
C(const C&) = delete;
};
int main()
{
C c({1, 2});
}
可変引数の数がゼロで、オブジェクトの初期化子リスト構築として扱われるC c({1, 2})
の最初のコンストラクターと一致することを完全に期待していました。C
{1, 2}
S
ただし、C の削除されたコピー コンストラクターと一致することを示すコンパイラ エラーが表示されます。
test.cpp: In function 'int main()':
test.cpp:17:15: error: use of deleted function 'C(const C &)'
test.cpp:12:5: error: declared here
私はそれがどのように機能するかを見ることができます.Cの有効な{1, 2}
初期化子として解釈できます.可変引数です...しかし、特に問題のコピーコンストラクターが削除されていることを考えると、なぜそれがより良い一致になるのかわかりません。1
S
2
ここで行われているオーバーロードの解決規則を説明して、コンストラクター呼び出しで S の名前を言及しない回避策があるかどうか教えてください。
編集: 誰かがスニペットが別のコンパイラでコンパイルされると述べたので、GCC 4.6.1 で上記のエラーが発生したことを明確にする必要があります。
EDIT 2:スニペットをさらに単純化して、さらに不穏な失敗を引き起こしました:
struct S
{
S(int, int = 0);
};
struct C
{
C(S);
};
int main()
{
C c({1});
}
エラー:
test.cpp: In function 'int main()':
test.cpp:13:12: error: call of overloaded 'C(<brace-enclosed initializer list>)' is ambiguous
test.cpp:13:12: note: candidates are:
test.cpp:8:5: note: C::C(S)
test.cpp:6:8: note: constexpr C::C(const C&)
test.cpp:6:8: note: constexpr C::C(C&&)
今回は、GCC 4.5.1 でも同じエラーが発生します (constexpr
暗黙的に生成されない s とムーブ コンストラクタを除く)。
これが言語設計者の意図したものであるとは信じがたいです...