Joh*_*ock 9 c++ constructor overloading ambiguity ambiguous
通过不成为隐式转换恶魔,这个问题很容易解决,但对我来说这似乎是一个奇怪的不一致。这是一个例子:
\n#include <unordered_set>\n\nvoid test1(int a, int b); // Overloaded function with two different\nvoid test1(std::unordered_set<char> set); // possible argument types\n\nstruct Test2 {\n Test2(int a, int b); // Overloaded constructor with two different\n Test2(std::unordered_set<char> set); // possible argument types\n};\n\nint main() {\n\n test1(123,456); // Testing out the overloaded functions\n test1({'a','b'}); // This works correctly with no ambiguity complaint\n // Neither GCC nor CLang mistake the initializer list of\n // two chars as possibly being two ints instead.\n\n Test2(123,456); // Testing out the overloaded constructors\n Test2({'a','b'}); // Error: more than one instance of constructor \n // "Test::Test" matches the argument list:C/C++(309)\n}\n\n// GCC & Clang complain about ambiguity for the implicit conversion in the constructor overload\n// GCC gives error: call of overloaded \xe2\x80\x98Test2(<brace-enclosed initializer list>)\xe2\x80\x99 is ambiguous\n// CLang gives error: call to constructor of 'Test2' is ambiguous\nRun Code Online (Sandbox Code Playgroud)\n我知道使用explicit Test2(int a, int b);解决了 CLang 中的问题,而 GCC 仍然给出了相同的抱怨。
为什么两个可以为重载函数推断出正确类型的参数的编译器拒绝为重载构造函数做同样的事情?
\n这是一件有趣的事。可以是用于构造临时对象的{'a', 'b'}请求,然后可以使用该临时对象来复制或移动构造另一个。例如:Test2(int a, int b)Test2Test2
Test2 b = {'a', 'b'};
Run Code Online (Sandbox Code Playgroud)
这不会发生
Test2({'a'});
Run Code Online (Sandbox Code Playgroud)
或者
Test2({'a','b','c'});
Run Code Online (Sandbox Code Playgroud)
因为它们与另一个构造函数不匹配。
快速解决方案是使用大括号而不是方括号
Test2{{'a','b'}};
Run Code Online (Sandbox Code Playgroud)
但我还没有找到一个明确的标准引用来解释为什么会这样。