模板转换运算符优先级和恒常性
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 资格时,重载选择似乎严格有意义。
标准的 13.3.3.1.2 点让我认为我应该使用模板转换运算符实例化进行恒等转换,转换为布尔值,T
=bool
,尽管显然隐藏在某处的微妙之处。有人可以启发我这里有什么规则吗?
相关规则在 [over.match.best] 中定义:
根据这些定义,一个可行的函数
F1
被定义为比另一个可行的函数更好的函数F2
如果对于所有参数i,ICSi(F1
) 不是一个比 ICSi(F2
) 更差的转换序列,然后 (1.3) — 对于某些参数 j,ICS j(F1
) 是比 ICSj(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
(标识 - 最高等级)的转换序列比从Foo*
到bool
(布尔转换 - 最低)的转换序列更好。
比较转换序列时,在转换结果类型之前会考虑参数的转换。 隐式对象参数(this
指针)被视为参数,限定转换(Foo -> Foo const
)比隐式对象参数上的标识转换差。 来自[over.match.best]:
1 - [...] 一个可行的函数F1被定义为比另一个可行的函数更好的函数 F2 如果对于所有参数 i,ICSi(F1) 不是比 ICSi(F2) 更差的转换序列,然后
— 对于某些参数 j,ICSj(F1) 是比 ICSj(F2) 更好的转换序列,或者,如果不是这样,[...]
因此,非const
限定成员转换运算符始终优于const
限定成员转换运算符,即使结果转换在后者上是精确的。
- const_cast静态数组以添加恒常性
- 自动模板参数、数据成员和恒常性
- 有没有办法检测自身内部的类恒常性?
- 为什么const_cast删除指针的恒常性,而不删除指向常量的指针的恒常性?
- 对指针和恒常性兼容性的引用
- 自定义容器中的括号运算符中的恒常性
- C++ 重载分辨率和恒常性
- C++17类模板演绎常性
- C++ 函数匹配和恒常性
- 如何忽略函数模板中的恒常性?
- 常量自动和对象恒常性
- 比较运算符 == 中的共享指针恒常性
- 添加额外的恒常性会导致编译器错误
- 删除模板化函数中的恒常性
- 无法正确理解我的恒常性
- 模板转换运算符优先级和恒常性
- const_iterator和恒常性const_iterator::value_type
- 使用const_cast来添加恒常性 - 坏主意?
- C++ 逻辑恒常性和 const方法的按值返回
- C++。为什么我不能编译此代码?使用const_cast去除恒常性有什么问题?