C++ 对带有 unsigned int 的重载函数的模糊调用

C++ ambiguous call to overloaded function with unsigned int

这似乎不一致。我为有符号类型 shortintlong long 重载了 3 个函数 f。如果您传递一个 unsigned short,那么它会被提升为下一个最大的有符号类型 int。但是,如果你传递 unsigned int 那么它不会被提升为有符号 long long 这是我所期望的,而是编译器抱怨对重载函数的模棱两可的调用。

void f(short x) { std::printf("f(short)\n"); }
void f(int x) { std::printf("f(int)\n"); }
void f(long long x) { std::printf("f(long long)\n"); }

int main()
{
    f((unsigned short)0); // Fine: calls f(int)
    // f((unsigned int)0); // Ambiguous: could be f(short), f(int) or f(long long) 
}

不一致,是的,但这是语言的方式,你必须应付,例如如果你想 f((unsigned int)0) 调用 long long 重载,那么提供一个包装器,

inline void f(unsigned int x) { f((long long)x); }

C++ 的设计者希望让您的两个案例都失败 重载解析。但是有一个遗留的东西(一直追溯到 "K&R" C),叫做 "default argument promotion",从本质上说,编译器会隐式地将所有窄于 int 的整数类型转换为 int 如果需要匹配函数签名,所有比 double 窄到 double 的浮点类型同上。

所以 f((unsigned short)0) 的情况确实很奇怪。

http://en.cppreference.com/w/cpp/language/implicit_conversion

积分促销 不会 让您从 unsigned int 提高到 long long

积分促销确实让您从unsigned short升至int

unsigned int 的积分转换被认为同样适合您的重载。

促销 结束int and/or unsigned int 除非您的源类型是需要更大整数类型的 enum适合它。

推广比转化更重要,所以你的第一个案例是明确的。第二种情况,没有提升路径,所以你的代码有歧义。