短
转换函数operator int()
由clang选择,operator bool() const
因为b
它不是const限定的,而bool的转换运算符是。
短的理由是,对于重载解析候选的功能(在适当位置隐式对象参数),在转换时b
向bool
是
operator bool (B2 const &);
operator int (B2 &);
第二个是更好的匹配,因为b
它不是const限定的。
如果两个功能都具有相同的资格(const
或不相同),operator bool
则选择它,因为它可以直接转换。
通过转换符号转换,逐步分析
如果我们同意布尔ostream的插入器(STD :: basic_ostream ::运算<<(布尔VAL),按照[ostream.inserters.arithmetic])被称为与值,从一个转换结果b
给bool
我们可以挖成转换。
1.强制转换表达式
b转换为布尔
(bool)b
评估为
static_cast<bool>(b)
根据C ++ 11,5.4 / 4 [expr.cast],因为const_cast
它不适用(此处未添加或删除const)。
如果对于本发明的变量t格式正确,则根据C ++ 11,5.2.9 / 4 [expr.static.cast]允许此静态转换bool t(b);
。根据C ++ 11,8.5 / 15 [dcl.init],这样的语句称为直接初始化。
2.直接初始化 bool t(b);
最少提及的标准段落的第16条规定(强调我的意思):
初始化程序的语义如下。目标类型是要初始化的对象或引用的类型,源类型是初始化器表达式的类型。
[...]
[...]如果源类型是(可能是cv限定的)类类型,则考虑转换函数。
列举了适用的转换函数,并通过重载分辨率选择了最佳的转换函数。
2.1哪些转换功能可用?
可用的转换函数是operator int ()
,operator bool() const
因为C ++ 11以来,12.3 / 5 [class.conv]告诉我们:
派生类中的转换函数不会在基类中隐藏转换函数,除非两个函数转换为相同类型。
虽然C ++ 11、13.3.1.5 / 1 [over.match.conv]指出:
考虑S的转换函数及其基类。
其中S是将从其转换的类。
2.2哪些转换功能适用?
C ++ 11,13.3.1.5 / 1 [over.match.conv](强调我的意思):
1 [...]假设“ cv1 T”是正在初始化的对象的类型,而“ cv S”是初始化表达式的类型,其中S为类类型,则按以下方式选择候选函数:考虑S的功能及其基类。那些未隐藏在S中并产生类型T或可以通过标准转换序列转换为类型T的类型的非显式转换函数是候选函数。
因此operator bool () const
适用,因为它没有隐藏在其中B2
并产生a bool
。
最后一个标准报价中强调的部分与使用的转换有关,operator int ()
因为这int
是可以通过标准转换序列转换为bool的类型。从int
到的转换bool
甚至不是一个序列,而是每个C ++ 11,4.12 / 1 [conv.bool]允许的普通直接转换。
算术,无作用域枚举,指针或指向成员类型的指针的prvalue可以转换为bool类型的prvalue。零值,空指针值或空成员指针值将转换为false;其他任何值都将转换为true。
这意味着operator int ()
同样适用。
2.3选择了哪种转换功能?
通过过载解析(C ++ 11,13.3.1.5/1 [over.match.conv])来选择适当的转换函数:
重载解析用于选择要调用的转换函数。
关于类成员函数的重载解析,有一个特殊的“怪癖”:“隐式对象参数”。
根据C ++ 11,13.3.1 [over.match.funcs],
[...]静态和非静态成员函数都有一个隐式对象参数[...]
对于非静态成员函数,此参数的类型-根据第4-节,为:
其中X是该函数是成员的类,而cv是成员函数声明上的cv限定词。
这意味着(根据C ++ 11,13.3.1.5 / 2 [over.match.conv]),在通过转换函数进行初始化时,
参数列表有一个参数,它是初始化器表达式。[注意:此参数将与转换函数的隐式对象参数进行比较。—尾注]
解决过载的候选函数为:
operator bool (B2 const &);
operator int (B2 &);
显然,operator int ()
如果B2
由于operator bool ()
要求进行资格转换而使用非常数类型的对象请求转换,则是更好的匹配。
如果两个转换函数共享相同的const限定符,那么这些函数的重载解析将不再有用。在这种情况下,转换(序列)排名就位。
3.operator bool ()
两个转换函数共享相同的const资格时为什么选择?
从B2
到的转换bool
是用户定义的转换序列(C ++ 11,13.3.3.1.2 / 1 [over.ics.user])
用户定义的转换序列由初始标准转换序列,随后的用户定义转换和第二标准转换序列组成。
[...]如果用户定义的转换由转换函数指定,则初始标准转换序列会将源类型转换为转换函数的隐式对象参数。
C ++ 11,13.3.3.2 / 3 [over.ics.rank]
基于更好的转换序列和更好的转换之间的关系,定义隐式转换序列的部分排序。
[...]如果用户定义的转换序列U1包含相同的用户定义的转换函数或构造函数或聚合初始化,并且比U1的第二个标准转换序列好,则它比另一个用户定义的转换序列U2更好。 U2的第二个标准转换序列。
第二标准转化箱子operator bool()
是bool
向bool
在情况(标识转换),而所述第二标准的转换operator int ()
是int
到bool
这是一个布尔值转换。
因此,operator bool ()
如果两个转换函数共享相同的const限定,则使用的转换顺序会更好。