![](/img/trans.png)
[英]priority of implicit conversion over template constructor and assignment operator for transparent lazyness
[英]Template conversion operator priority & constness
我有类似的东西:
#include <iostream>
class Foo;
struct Test
{
template <typename T>
operator T() const // <----- This const is what puzzles me
{
std::cout << "Template conversion" << std::endl;
return T{};
}
operator Foo*()
{
std::cout << "Pointer conversion" << std::endl;
return nullptr;
}
};
int main()
{
Test t;
if (t)
{
std::cout << "ahoy" << std::endl;
}
bool b = (bool)t;
Foo* f = (Foo*)t;
}
它构建良好,但当我运行它,而我期望得到
$> ./a.out
Template conversion
Template conversion
Pointer conversion
我反而得到了
$> ./a.out
Pointer conversion
Pointer conversion
Pointer conversion
如果我删除const,或使Test实例为const,那么一切都按预期工作。 更确切地说,当两个运算符具有相同的const限定时,过载选择似乎是有意义的。
13.3.3.1.2标准的要点让我觉得我应该得到一个身份转换,转换为bool,使用模板转换运算符实例化与T
= bool
,虽然显然有一个隐藏在某处的微妙。 有人可以告诉我这里有什么规则发挥作用吗?
相关规则在[over.match.best]中定义:
给定这些定义,如果对于所有参数i ,ICS i (
F1
)不是比ICS i (F2
)更差的转换序列,则可行函数F1
被定义为比另一个可行函数F2
更好的函数,然后
(1.3) - 对于某些参数j ,ICS j (F1
)是比ICS j (F2
)更好的转换序列,或者,如果不是,
(1.4) - 上下文是用户定义的转换初始化(见8.5,13.3.1.5和13.3.1.6)以及从返回类型F1
到目标类型的标准转换序列(即实体的类型)被初始化)是比从返回类型F2
到目标类型的标准转换序列更好的转换序列。
让我们看看第一个bool
案例。 我们有两个可行的候选人:
Test::operator T<bool>() const;
Test::operator Foo*();
两者都使用非const
Test
进行调用。 对于第二次重载,不需要转换 - 转换序列只是完全匹配。 但是,对于第一次重载,隐式this
参数需要进行从Test
到const Test
的限定转换。 因此,第二个重载是首选 - 我们没有进入讨论返回类型的第二步。
如果我们放弃const
,那么可行的候选人将成为:
Test::operator T<bool>();
Test::operator Foo*();
在这里,两个候选者具有相同的转换序列同样可行,但是bool
模板是优选的,因为从返回类型bool
到bool
的转换序列(Identity - 最高等级)是比从Foo*
到bool
更好的转换序列(布尔转换) - 最低的)。
比较转换序列时,在转换结果类型之前会考虑参数的转换。 隐式对象参数( this
指针)被视为参数,限定转换( Foo -> Foo const
)比隐式对象参数的标识转换更差。 来自[over.match.best] :
1 - [...]一个可行的函数F1被定义为比另一个可行函数F2更好的函数如果对于所有参数i,ICSi(F1)不是比ICSi(F2)更差的转换序列,然后
- 对于某些参数j,ICSj(F1)是比ICSj(F2)更好的转换序列,或者,如果不是,[...]
所以非const
-qualified成员转换操作符总是比一个更好的const
-qualified一个,即使结果转换确切后者。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.