在重载分辨率中,选择使用模糊转换序列的函数是否必然导致调用不正确? [英] In overload resolution, does selection of a function that uses the ambiguous conversion sequence necessarily result in the call being ill-formed?

查看:99
本文介绍了在重载分辨率中,选择使用模糊转换序列的函数是否必然导致调用不正确?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在研究此SO问题的答案时出现了问题。考虑下面的代码:

The question arose while I was researching the answer to this SO question. Consider the following code:

struct A{
    operator char() const{ return 'a'; }
    operator int() const{ return 10; }
};

struct B {
    void operator<< (int) { }
};

int main()
{
    A a;
    B b;
    b << a;
}

转换 a int 可以通过 a.operator char()后跟一个积分促销,或 a.operator int()后跟一个身份转换(即,根本没有转换)。标准说,(§13.3.3.1[over.best.ics] / p10,脚注省略,加粗我的所有引号都来自N3936):

The conversion of a to int can be either via a.operator char() followed by an integral promotion, or a.operator int() followed by an identity conversion (i.e., no conversion at all). The standard says that (§13.3.3.1 [over.best.ics]/p10, footnote omitted, bolding mine; all quotes are from N3936):


如果存在几个不同的转换序列,每个将参数
转换为参数类型,则与该参数相关联的隐式转换序列
被定义为唯一转换
序列指定转义序列。对于
目的如
13.3.3.2中所描述的对隐式转换序列进行排序的目的,不明确的转换序列被视为用户定义的序列,其与任何其他
用户定义的转换序列不可区分。 如果使用
不明确的转换序列的函数被选择为最好的可行函数
,则调用将是错误的,因为调用中
参数之一的转换

这里, B :: operator< code>是唯一可行的候选项 - 因此是最好的可行候选项,即使参数的转换序列是不明确的转换序列。根据粗体句,那么,调用应该是不成形的,因为调用中的一个参数的转换是不明确的。

Here, B::operator<<(int) is the only viable candidate - and hence is the best viable candidate, even though the conversion sequence for the parameter is the ambiguous conversion sequence. According to the bolded sentence, then, the call should be ill-formed because "the conversion of one of the arguments in the call is ambiguous".

然而,我测试的编译器(g ++,clang和MSVC)实际上报告错误,这是有道理的,因为在通过重载分辨率选择调用函数之后,函数的参数(8.3.5)应该用相应的
参数初始化(8.5,12.8,12.1)(§5.2.2[expr.call] / p4)。这个初始化是复制初始化(§8.5[dcl.init] / p15),并且根据§8.5[dcl.init] / p17,导致新一轮的重载分辨率来确定转换函数使用:

Yet no compiler that I tested (g++, clang, and MSVC) actually reports an error, which makes sense because after the function to call is selected through overload resolution, the function's "parameter (8.3.5) shall be initialized (8.5, 12.8, 12.1) with its corresponding argument" (§5.2.2 [expr.call]/p4). This initialization is copy-initialization (§8.5 [dcl.init]/p15), and according to §8.5 [dcl.init]/p17, results in a new round of overload resolution to determine the conversion function to use:


初始化器的语义如下。 目标类型
是要初始化的对象或引用的类型,
源类型是初始化表达式的类型。如果初始化程序不是单个(可能是括号括号的)表达式,则不定义
源类型。

The semantics of initializers are as follows. The destination type is the type of the object or reference being initialized and the source type is the type of the initializer expression. If the initializer is not a single (possibly parenthesized) expression, the source type is not defined.


    < ]
  • 如果目标类型是(可能是cv限定的)类类型:[...]

  • (可能是cv限定的)类类型,考虑转换函数。适用的转换
    函数是枚举的(13.3.1.5),最好的转换是通过重载分辨率(13.3)选择
    。调用用户定义的转换
    选择将初始化器表达式转换为正在初始化的
    对象。

  • [...]

  • [...]
  • If the destination type is a (possibly cv-qualified) class type: [...]
  • Otherwise, if the source type is a (possibly cv-qualified) class type, conversion functions are considered. The applicable conversion functions are enumerated (13.3.1.5), and the best one is chosen through overload resolution (13.3). The user-defined conversion so selected is called to convert the initializer expression into the object being initialized. If the conversion cannot be done or is ambiguous, the initialization is ill-formed.
  • [...]

在这一轮重载解析中,在§13.3.3[over.match.best] / p1:

And in this round of overload resolution, there is a tiebreaker in §13.3.3 [over.match.best]/p1:


一个可行函数 F1 被定义为比另一个
可行函数F2更好的函数如果对于所有参数 i ICSi(F1)不是更糟的
转换序列比 ICSi(F2),然后

a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then


  • / code>, ICSj(F1)是比 ICSj(F2)更好的转换序列,如果不是这样,

  • 上下文是通过用户定义转换(见8.5,13.3.1.5和13.3.1.6)的初始化和从<$的返回类型的标准转换序列c $ c> F1 到目标类型(即,被初始化的
    实体的类型)是比来自返回类型的
    标准转换序列更好的转换序列 F2
    目的地类型。

  • for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that,
  • 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.

示例和列表的其余部分省略)

(Example and remainder of the list omitted)

由于 int int (完全匹配排名)的标准转换顺序优于 char int (促销等级),第一次击败第二个,并且应该没有歧义 - 由 operator int()定义的转换将用于初始化,然后与§13.3.3.1[over.best.ics] / p10中的句子相矛盾,因为该语句会因为模糊性而导致函数调用失败。

Since the standard conversion sequence from int to int (Exact Match rank) is better than the standard conversion sequence from char to int (Promotion rank), the first beats the second, and there should be no ambiguity - the conversion defined by operator int() will be used for the initialization, which then contradicts the sentence in §13.3.3.1 [over.best.ics]/p10 that says the function call will be ill-formed because of ambiguity.

在上面的分析中有什么错误,或者是那句话是标准中的错误?

Is there anything wrong in the above analysis, or is that sentence a bug in the standard?

推荐答案

当为用户定义的转换序列决定最佳的用户定义转换时,我们有一个重载候选集。

When deciding the best user-defined conversion for a user-defined conversion sequence we have an overload candidate set.

§13.3.3/ p1说:

§13.3.3/p1 says:


定义ICSi(F)如下:

Define ICSi(F) as follows:


  • [...]

  • [...]

let ICSi(F)表示隐式转换序列,将列表中的第i个参数转换为
类型的可行函数F的第i个参数。13.3.3.1定义隐式转换序列,
13.3.3.2定义了一个隐式转换序列是什么意思是更好的转换序列
或更差的转换序列

let ICSi(F) denote the implicit conversion sequence that converts the i-th argument in the list to the type of the i-th parameter of viable function F. 13.3.3.1 defines the implicit conversion sequences and 13.3.3.2 defines what it means for one implicit conversion sequence to be a better conversion sequence or worse conversion sequence than another.

给定这些定义,可行函数F1被定义为比另一个更好的函数可行函数
F2如果对于所有参数i,ICSi(F1)不是比ICSi(F2)更糟的转换序列,然后

- [...]

- 上下文是用户定义转换的初始化(见8.5,13.3.1.5和13.3.1.6)
从F1的返回类型到目标类型(即,正在初始化的
实体的类型)的标准转换序列是比标准转换序列更好的转换序列,来自
返回类型

这适用于

§13.3.3.1.2/ p2

§13.3.3.1.2/p2


2第二个标准转换序列将用户定义转换的结果转换为目标
类型的序列。 由于隐式转换序列是初始化,用户定义转换初始化
的特殊规则适用于为用户定义的
转换序列选择最佳的用户定义转换时(见第13.3节)。 $ b <$>

2 The second standard conversion sequence converts the result of the user-defined conversion to the target type for the sequence. Since an implicit conversion sequence is an initialization, the special rules for initialization by user-defined conversion apply when selecting the best user-defined conversion for a user-defined conversion sequence (see 13.3.3 and 13.3.3.1).

$ <$> $ <$>

and therefore the conversion sequence involving operator int is selected as best match.

最后,我将把§13.3.3.1/ p10改为

Finally I would rephrase §13.3.3.1/p10 as

如果存在几个不同的转换序列,每个转换参数为参数类型,并且不可能确定最佳候选,
隐式转换与参数相关的序列被定义为指定不明确转换序列的唯一转换序列
。为了对如13.3.3.2中所描述的隐式转换序列
进行排序,不确定转换序列被视为用户定义的序列,其与任何其他用户定义的转换序列134不可区分。如果使用不明确的
转换序列的函数被选择为最佳可行函数,则调用将是不成立的,因为调用中的一个参数的转换
是不明确的。

If several different sequences of conversions exist that each convert the argument to the parameter type and it was not possible to determine a best candidate, the implicit conversion sequence associated with the parameter is defined to be the unique conversion sequence designated the ambiguous conversion sequence. For the purpose of ranking implicit conversion sequences as described in 13.3.3.2, the ambiguous conversion sequence is treated as a user-defined sequence that is indistinguishable from any other user-defined conversion sequence134. If a function that uses the ambiguous conversion sequence is selected as the best viable function, the call will be ill-formed because the conversion of one of the arguments in the call is ambiguous.

这篇关于在重载分辨率中,选择使用模糊转换序列的函数是否必然导致调用不正确?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆