【问题标题】:Why is it ambiguous to call overloaded ambig(long) and ambig(unsigned long) with an integer literal?为什么用整数文字调用重载的 ambig(long) 和 ambig(unsigned long) 会模棱两可?
【发布时间】:2012-01-07 17:01:18
【问题描述】:

编译时

void ambig(  signed long) { }
void ambig(unsigned long) { }

int main(void) { ambig(-1); return 0; }

我明白了

error C2668: 'ambig' : ambiguous call to overloaded function
    could be 'void ambig(unsigned long)'
    or 'void ambig(long)'
while trying to match the argument list '(int)'

我知道我可以通过说 -1L 而不是 -1 来“修复”它,但是为什么/如何确切地认为这首先是模棱两可的?

【问题讨论】:

    标签: c++ visual-c++ ambiguity


    【解决方案1】:

    您将 int 传递给此重载函数。

    虽然人类的直觉认为ambig(signed long) 应该是首选,因为您的输入是一个负整数(不能用unsigned long 表示),这两种转换实际上在C++ 中的“优先级”中是等价的。

    也就是说,intunsigned long 的转换被认为与intsigned long 一样有效,并且两者都不优先于另一个。

    另一方面,如果您的参数已经是long 而不是int,则与signed long 存在完全匹配,无需转换。 This avoids the ambiguity.

    void ambig(  signed long) { }
    void ambig(unsigned long) { }
    
    int main(void) { ambig(static_cast<long>(-1)); return 0; }
    

    “只是其中之一”。


    [C++11: 4.13/1]:("整数转换等级")

    每个整数类型都有一个整数转换等级,定义如下:

    • [..]
    • 有符号整数类型的等级应大于任何尺寸较小的有符号整数类型的等级。
    • long long int的等级大于long int的等级大于int的等级,大​​于大于short int 的秩,应大于signed char 的秩。
    • 任何无符号整数类型的等级都应等于相应有符号整数类型的等级。
    • [..]

    [ 注意: 整数转换等级用于定义积分提升(4.5)和通常的算术转换(第 5 条)。 ——尾注 ]

    重载解析很复杂,在[C++11: 13.3]中定义;我不会在这里引用大部分内容来让你厌烦。

    这里有一个亮点:

    [C++11: 13.3.3.1/8]: 如果不需要转换即可将参数匹配到参数类型,则隐式转换序列是由恒等转换 (13.3.3.1.1) 组成的标准转换序列。

    [C++11: 13.3.3.1/9]: 如果找不到将实参转换为参数类型的转换序列,或者转换格式不正确,则无法形成隐式转换序列。

    [C++11: 13.3.3.1/10]: 如果存在多个不同的转换序列,每个转换序列将参数转换为参数类型,则与参数关联的隐式转换序列被定义为指定为模糊转换序列的唯一转换序列。为了对 13.3.3.2 中描述的隐式转换序列进行排序,模糊转换序列被视为用户定义的序列,与任何其他用户定义的转换序列没有区别134。如果选择使用不明确的转换序列的函数作为最佳可行函数,则调用将是非良构的,因为调用中的一个参数的转换是不明确的。

    • /10 是您遇到的情况; /8 是与 long 参数一起使用的情况。

    【讨论】:

    • 等等,但是intlong 始终是无损转换。 intunsigned long 有一半是有损的。他们如何/为什么排名相同?!
    • 只是好奇:有什么理由不使用-1L 而不是那个演员?
    • @sepp2k:哇,我明白了……o__o(我想到了“每日#$!”……)
    • @Mehrdad:上面第三个粗体项目符号。至于“为什么”,谁知道呢!?
    • @Mehrdad:这可能是因为在典型的较旧的 16 位系统上,intunsigned long 不会有损(我相信?)。 也许。似乎有点愚蠢。
    【解决方案2】:

    常量-1 的类型为int。所以你用int 作为参数调用ambigambig 没有接受int 的重载,所以我们必须看看我们可以做的隐式转换。 int 可以隐式转换为longunsigned long(除其他外),这两者都是ambig 的有效参数。因此编译器不知道要选择哪种转换,您需要手动转换(或使用 long 常量 (-1l) 而不是 int 常量开始)。

    -1 是负数这一事实并没有考虑在内,因为编译器不查看参数值,只查看其类型。

    【讨论】:

      【解决方案3】:

      因为-1int 类型。并且int 可以隐式转换为signed longunsigned long

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-05-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-20
        • 2016-07-29
        相关资源
        最近更新 更多