gpt4 book ai didi

c++ - 通过初始标准转换序列区分用户自定义转换序列

转载 作者:太空狗 更新时间:2023-10-29 20:28:58 25 4
gpt4 key购买 nike

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

13.3.3 Best viable function [over.match.best]

[...] a viable function F1 is defined to be a better function than another viable function F2 if [...]

  • the context is an initialization by user-defined conversion (see 8.5, 13.3.1.5, and 13.3.1.6) and the standard conversion sequence from the return type of F1 to the destination type (i.e., the type of the entity being initialized) is a better conversion sequence than the standard conversion sequence from the return type of F2 to the destination type.

13.3.3.2 Ranking implicit conversion sequences [over.ics.rank]

3 - Two implicit conversion sequences of the same form are indistinguishable conversion sequences unless one of the following rules applies: [...]

  • User-defined conversion sequence U1 is a better conversion sequence than another user-defined conversion sequence U2 if they contain the same user-defined conversion function or constructor or aggregate initialization and the second standard conversion sequence of U1 is better than the second standard conversion sequence of U2.

据我了解,13.3.3 允许编译器区分不同的用户定义转换运算符,而 13.3.3.2 允许编译器区分不同的函数 (某些函数 f 的重载),每个函数都需要在其参数中进行用户定义的转换(请参阅我对 Given the following code (in GCC 4.3) , why is the conversion to reference called twice? 的侧边栏)。

是否有其他规则可以区分用户自定义的转换序列?答案在https://stackoverflow.com/a/1384044/567292表示 13.3.3.2:3 可以根据隐式对象参数(转换运算符)的 cv 限定或构造函数或聚合初始化的单个非默认参数的 cv 限定来区分用户定义的转换序列,但我不鉴于这需要比较各个用户定义的转换序列的第一个标准转换序列,而标准似乎没有提及,所以看不出这有什么关系。

假设S1优于S2,其中S1为U1的第一个标准转换序列,S2为U2的第一个标准转换序列,是否推出U1优于U2?换句话说,这段代码格式是否正确?

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

g++ (4.5.1), Clang (3.0) 和 Comeau (4.3.10.1) 接受它,更喜欢非 const 限定的 A::operator int(),但我希望它会因为模棱两可和格式错误而被拒绝。这是标准的缺陷还是我对它的理解?

最佳答案

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

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

在表达式foo(a) 中,foo 显然命名了一个非重载的非成员函数。该调用需要复制初始化 (8.5p14) double 类型的函数参数,使用单个表达式 a,它是类类型 A< 的左值.

由于目标类型 double 不是 cv 限定的类类型,而源类型 A 是,候选函数由第 13.3.1.5 节定义,其中 S=AT=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 的左值引用类型)绑定(bind)到表达式 a( 类型的左值>A).
  • ICS1(F2):将隐式对象参数(对 const A 的类型左值引用)绑定(bind)到表达式 a(类型为 A).

由于没有进行派生到基础的转换,这些引用绑定(bind)被认为是身份转换的特殊情况 (13.3.3.1.4p1)。是的,这两个功能都是可行的。

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

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

现在,如果 foo 被重载,则需要比较参数 a 上的用户定义转换。那么用户定义的转换(identity + A::operator int() + int to double)将与其他隐式转换进行比较序列。

关于c++ - 通过初始标准转换序列区分用户自定义转换序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11555950/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com