Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++11 通过初始标准转换序列区分用户定义的转换序列_C++11_C++_Constructor_Implicit Conversion_Language Lawyer_Conversion Operator - Fatal编程技术网

C++11 通过初始标准转换序列区分用户定义的转换序列

C++11 通过初始标准转换序列区分用户定义的转换序列,c++11,c++,constructor,implicit-conversion,language-lawyer,conversion-operator,C++11,C++,Constructor,Implicit Conversion,Language Lawyer,Conversion Operator,该标准似乎提供了两条规则,用于区分涉及用户定义转换运算符的隐式转换序列: 13.3.3最佳可行功能[超过.匹配.最佳] […]可行函数F1被定义为比另一个可行函数更好的函数 F2如果[…] 上下文是用户定义转换的初始化(见8.5、13.3.1.5和13.3.1.6)和 从F1返回类型到目标类型的标准转换顺序(即 实体(正在初始化)是一个比标准转换序列更好的转换序列 将F2的返回类型设置为目标类型 13.3.3.2隐式转换序列排名[超过ics排名] 3-两个相同形式的隐式转换序列是不可区分的

该标准似乎提供了两条规则,用于区分涉及用户定义转换运算符的隐式转换序列:

13.3.3最佳可行功能[超过.匹配.最佳] […]可行函数F1被定义为比另一个可行函数更好的函数 F2如果[…]

  • 上下文是用户定义转换的初始化(见8.5、13.3.1.5和13.3.1.6)和 从F1返回类型到目标类型的标准转换顺序(即 实体(正在初始化)是一个比标准转换序列更好的转换序列 将F2的返回类型设置为目标类型
13.3.3.2隐式转换序列排名[超过ics排名] 3-两个相同形式的隐式转换序列是不可区分的转换序列,除非其中一个 下列规则适用:[……]

  • 如果用户定义的转换序列U1包含相同的用户定义的转换函数或构造函数或聚合,则用户定义的转换序列U1比另一个用户定义的转换序列U2更好 U1的初始化和第二个标准转换顺序优于第二个标准 U2的转换序列
据我所知,13.3.3允许编译器区分不同的用户定义的转换运算符,而13.3.3.2允许编译器区分不同的函数(某些函数的重载
f
),每个函数的参数都需要用户定义的转换(请参见我的侧栏)

是否有其他规则可以区分用户定义的转换序列?回答at表明13.3.3.2:3可以根据隐式对象参数(转换运算符)或单个非默认参数(构造函数)或聚合初始化的cv限定来区分用户定义的转换序列,但我不认为这有什么关系,因为这需要比较各个用户定义的转换序列的第一个标准转换序列,而该标准似乎没有提到

假设S1比S2好,其中S1是U1的第一个标准转换序列,S2是U2的第一个标准转换序列,那么U1比U2好吗?换句话说,这个代码是否格式正确

struct A {
    operator int();
    operator char() const;
} a;
void foo(double);
int main() {
    foo(a);
}

(4.5.1)、(3.0)和(4.3.10.1)接受它,更喜欢非常量限定的
A::operator int()
,但我希望它会被拒绝,因为它不明确,因此格式不正确。这是标准中的缺陷还是我对它的理解中的缺陷?

这里的技巧是,从类类型转换为非类类型实际上并不将任何用户定义的转换作为隐式转换序列进行排序

struct A {
    operator int();
    operator char() const;
} a;
void foo(double);
int main() {
    foo(a);
}
在表达式
foo(a)
中,
foo
显然命名了一个非重载的非成员函数。调用需要使用单个表达式
a
,对
double
类型的函数参数进行复制初始化(8.5p14),该表达式是类类型
a
的左值

由于目标类型
double
不是cv限定类类型,但源类型
a
是,候选函数由第13.3.1.5节定义,其中
S=a
T=double
。仅考虑类
A
中的转换函数和
A
的任何基类。在以下情况下,转换函数位于候选函数集中:

  • 它不隐藏在类
    A
    中,并且
  • 它不是显式的(因为上下文是复制初始化),并且
  • 标准转换序列可以将函数的返回类型(不包括任何引用限定符)转换为目标类型
    double
好的,两个转换函数都符合条件,所以候选函数是

A::operator int();        // F1
A::operator char() const; // F2
使用13.3.1p4中的规则,每个函数的参数列表中只有隐式对象参数
F1
的参数列表是“(对
A
的左值引用)”,
F2
的参数列表是“(对
const A的左值引用
)”

接下来,我们检查功能是否可行(13.3.2)。每个函数在其参数列表中都有一个类型,并且有一个参数。每个参数/参数对是否都有隐式转换序列?当然可以:

  • ICS1(F1)
    :将隐式对象参数(类型左值引用到
    A
    )绑定到表达式
    A
    (类型左值
    A
  • ICS1(F2)
    :将隐式对象参数(对
    const A
    的类型左值引用)绑定到表达式
    A
    (类型左值
    A
因为并没有进行从派生到基的转换,所以这些引用绑定被认为是标识转换的特例(13.3.3.1.4p1)。是的,这两种功能都是可行的

现在我们必须确定一个隐式转换序列是否优于另一个。这属于13.3.3.2p3中大列表中的第五个子项:除顶级cv限定符外,它们都是指向相同类型的引用绑定。由于
ICS1(F2)
的引用类型比
ICS1(F1)
的引用类型更符合cv,因此
ICS1(F1)
优于
ICS1(F2)

因此,
F1
A::operator int()
是最可行的函数。甚至没有对用户定义的转换(严格定义由SCS+(转换构造函数或转换函数)+SCS组成的IC类型)进行比较

现在,如果
foo
被重载,则需要比较参数
a
上的用户定义转换。s