为什么不缩小会影响重载分辨率?

Bar*_*rry 25 c++ language-lawyer overload-resolution c++11

考虑以下:

struct A {
    A(float ) { }
    A(int ) { }
};

int main() {
    A{1.1}; // error: ambiguous
}
Run Code Online (Sandbox Code Playgroud)

这无法编译时出现关于模糊重载的错误A::A.两位候选人都被认为是可行的,因为要求很简单:

第二,为了F成为一个可行的函数,每个参数都应该存在一个隐式转换序列(13.3.3.1),它将该参数转换为相应的参数F.

虽然存在从隐式转换序列doubleint,该A(int )过载不是实际可行的(在规范,非C++ -标准的意义上) -这将涉及一个收缩转换,因此是形成不良.

为什么在确定可行的候选人的过程中不考虑缩小转换?尽管只有一个候选人可行,但是有没有其他情况下过载被认为是模棱两可的?

Yak*_*ont 15

问题在于可以不基于类型检测缩小转换的事实.

在C++中,有很复杂的方法可以在编译时生成值.

阻止缩小转换是一件好事.使C++的重载分辨率比现在更复杂是一件坏事.

在确定过载分辨率时忽略缩小转换规则(这使得过载分辨率完全与类型有关),然后在所选过载导致转换变窄时出错,使过载分辨率变得更加复杂,并增加了检测和防止的方法缩小转换率.

只有一个候选者可行的两个例子是在实例化期间"迟到"失败的模板函数,以及复制列表初始化(explicit考虑构造函数,但如果选择它们,则会出现错误).类似地,具有该影响的重载分辨率将使重载分辨率比现在更复杂.

现在,有人可能会问,为什么不将纯粹的转换缩小到类型系统?

缩小转换纯粹是基于类型的转换是不可行的.这些更改可能会破坏编译器可能证明有效的大量"遗留"代码.当大多数错误是实际错误而不是新的编译器版本是一个混蛋时,扫描代码库所需的工作更有价值.

unsigned char buff[]={0xff, 0x00, 0x1f};
Run Code Online (Sandbox Code Playgroud)

这会在类型的缩小转换下失败,就像0xff类型一样int,并且这种代码非常常见.

如果这样的代码需要对int文字进行毫无意义的文字修改,那么unsigned char我们设置一个标志来告诉编译器关闭愚蠢的错误,可能会导致扫描结束.

  • @Barry然后`unsigned char buff [] = {0xff,0x00,0x1f};`中断没有充分理由(`int`到`unsigned char`会缩小,即使`int`在`unsigned的范围内char`).破坏可证明没有错误的现有代码只应该有充分的理由.缩小转换是否会在没有该功能的情况下实现?我们刚刚进行了大规模的扫描,以便为代码库添加缩小的转换(以及其他C++ 11/14功能)支持:事实上,实际"oops"的许多中断使得它不那么诱人而只是告诉它编译器闭嘴. (5认同)
  • *copy-list-initialization*有一个类似的规则 - 它在重载决策中考虑所有构造函数,然后如果所选构造函数是显式的,则呈现错误的代码.这是IMO比复制初始化更好,只包括重载集中的非显式构造函数. (3认同)

bam*_*s53 8

  • 缩小是编译器只知道内置类型的东西.用户定义的隐式转换不能标记为缩小.

  • 首先,不应允许缩小转换.(不幸的是,它是C兼容性所必需的.{}初始化禁止缩小内置类型,这已得到一定程度的纠正.)

鉴于这些,过载规则无需提及这种特殊情况是有道理的.这可能是偶然的便利,但并不是那么有价值.IMO通常会更好地减少重载决策所涉及的因素,并拒绝更多不明确的事情,迫使程序员明确地解决这些问题.


另外,当double不是常量表达式或double太大时,double to float是缩小转换.

#include <iostream>
#include <iomanip>

int main() {
    double d{1.1};
    float f{d};
    std::cout << std::setprecision(100) << d << " " << f << '\n';
}
Run Code Online (Sandbox Code Playgroud)

这通常会产生错误:

main.cpp:7:13: error: non-constant-expression cannot be narrowed from type 'double' to 'float' in initializer list [-Wc++11-narrowing]
    float f{d};
            ^
Run Code Online (Sandbox Code Playgroud)