当我将enum指定为第二个参数时,为什么VisualC ++(2008)会混淆'C2666:2重载具有类似的转换',但是当我定义bool类型时却没有?
不应该键入匹配已经排除了第二个构造函数,因为它是'basic_string'类型的吗?
#include <string>
using namespace std;
enum EMyEnum { mbOne, mbTwo };
class test {
public:
#if 1 // 0 = COMPILE_OK, 1 = COMPILE_FAIL
test(basic_string<char> myString, EMyEnum myBool2) { }
test(bool myBool, bool myBool2) { }
#else
test(basic_string<char> myString, bool myBool2) { }
test(bool myBool, bool myBool2) { }
#endif
};
void testme() {
test("test", mbOne);
}
我可以通过指定引用来解决这个问题。 basic_string&amp; myString'但不是'const basic_string&amp; myString'。
还通过“test((basic_string)”test“,mbOne”显式调用;“也有效。
我怀疑这与通过固有的'!= 0'解析为bool的每个表达式/类型有关。
对所有评论都很好奇:)
答案 0 :(得分:5)
模糊性的原因是,只有当一个候选函数的参数都不比另一个参数的参数更差时,它才优于另一个候选函数。
问题是字符串文字的类型为const char[5]
,可以转换为std::string
(通过转换构造函数)和bool
(因为数组可以衰减)指针,任何指针都可以隐式转换为bool
)。转换为bool
是首选,因为它是标准转化,标准转化优先于用户定义的转化。
所以,考虑一下“破损”的重载:
test(basic_string<char> myString, EMyEnum myBool2) { } // (1)
test(bool myBool, bool myBool2) { } // (2)
第一个参数是const char[5]
并且更喜欢(2)
(根据上面的描述)。第二个参数是EMyEnum
并且更喜欢(1)
,这是完全匹配;需要进行转换以匹配(2)
(枚举可以隐式转换为bool
)。
现在考虑第二种情况:
test(basic_string<char> myString, bool myBool2) { } // (3)
test(bool myBool, bool myBool2) { } // (4)
第一个参数仍然更喜欢(4)
,但现在第二个参数可以同等地匹配(3)
和(4)
。因此,编译器可以选择(4)
并且没有歧义。
如果你消除了第一个参数所需的转换,例如,
,就没有歧义test(basic_string<char>("test"), mbOne);
因为两个参数都与(1)
完全匹配。