枚举,构造函数重载具有类似的转换

Dav*_*ley 3 c++ enums constructor-overloading visual-c++

当我将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);
}
Run Code Online (Sandbox Code Playgroud)

我可以通过指定引用来解决这个问题.basic_string&myString'但不是'const basic_string&myString'.

也通过"test((basic_string)"test",mbOne"显式调用;" 也有效.

我怀疑这与通过固有的'!= 0'解析为bool的每个表达式/类型有关.

好奇的评论都一样:)

Jam*_*lis 5

模糊性的原因是,只有当一个候选函数的参数都不比另一个参数更差时,它才优于另一个候选函数.

问题是字符串文字,其类型const char[5]可以转换为std::string(通过转换构造函数)和a bool(因为数组可以衰减为指针,并且任何指针都可以隐式转换为bool).转换bool为首选是因为它是标准转化,标准转化优先于用户定义的转化.

所以,考虑"破坏"的重载:

test(basic_string<char> myString, EMyEnum myBool2) { }  // (1)
test(bool myBool, bool myBool2) { }                     // (2)
Run Code Online (Sandbox Code Playgroud)

第一个参数是a const char[5]并且更喜欢(2)(根据上面的描述).第二个参数是a EMyEnum并且更喜欢(1),这是完全匹配; 需要进行转换才能匹配(2)(枚举可以隐式转换为a bool).

现在考虑第二种情况:

test(basic_string<char> myString, bool myBool2) { }    // (3)
test(bool myBool, bool myBool2) { }                    // (4)
Run Code Online (Sandbox Code Playgroud)

第一个参数还是比较喜欢(4),但是现在的第二个参数可以同时匹配(3)(4)平等.因此,编译器可以选择(4)并且没有歧义.

如果你消除了第一个参数所需的转换,就没有歧义,例如,

test(basic_string<char>("test"), mbOne);
Run Code Online (Sandbox Code Playgroud)

因为两个参数都(1)完全匹配.