为什么我可以阻止基元的隐式转换,而不是用户定义类型的隐式转换
Why can I prevent implicit conversions for primitives but not user-defined types?
高完整性C++标准建议可以删除函数的右值参数,从而防止隐式转换。
http://www.codingstandard.com/rule/8-3-4-define-delete-functions-with-parameters-of-type-rvalue-reference-to-const/
我发现基元和用户定义类型的行为非常不同。
struct A { };
struct B { B(const A& ) {} };
template <class T>
void foo(const T&&) = delete; // 1 - deleted rvalue overload. const intentional.
void foo(B) {} // 2
void foo(int) {} // 3
int main(int argc, char* argv[])
{
A a;
foo(a); // This resolves to 2
foo(3.3); // This resolves to 1
foo(2); // This resolves to 3 (as expected).
}
为什么删除的右值重载会阻止隐式转换为 int,但不能阻止从一个用户定义类型到另一个用户定义类型?
高完整性C++标准表明,右值参数 可以删除函数,从而防止隐式转换。
否,只有转发参考重载才会对重载集中的所有其他重载禁用 ICS(隐式转换序列(。使其成为转发引用,并查看禁用 ICS (Coliru 链接(
template <class T>
void foo(const T&&) = delete; // introduces a qualification match
上面的代码将资格匹配添加到重载。因此,ICS仍在发挥作用。
foo(3.3)
失败的原因是因为3.3
是 double
类型的 prvalue,它与 rvalue 重载的匹配比转换为 int
更好。因为资格匹配的排名优于转换匹配
在代码中,用户定义类型和基元类型在处理上没有区别。这两行行为之间的区别:
foo(a);
foo(3.3);
是a
是右值,3.3
是右值。 右值参数与重载1
匹配(仅接受右值(,左值参数不匹配。
如果您尝试使用 rvalue 参数调用 foo<A>
,它也将匹配1
并失败,例如 foo(A{});
.
有 3 种可能的重载
- 1 是可行的。
- 2 是可行的
- 3 不是
2 是更好的匹配(模板(非完全匹配(与常规方法(一个用户定义转换((。
你可以看看 http://en.cppreference.com/w/cpp/language/overload_resolution查看所需的完整规则集
相关文章:
- Visual C++(VS2017)中用户定义的转换不明确
- 参数包构造函数在类模板中隐藏用户定义的转换
- C++:用户定义的显式类型转换函数错误
- 用户定义的转换不能在C++中使用static_cast
- 用户定义的转换无法指定返回类型
- 是否可以创建一个用户定义的文本,将字符串文本转换为 own 类型的数组?
- 如何索引转换后的用户数据值?
- 将二进制转换为十进制,我如何要求用户仅输入二进制
- 过载分辨率和用户定义的转换
- 使用用户定义的操作隐式转换为类型
- C++列表初始化允许多个用户定义的转换
- 表达式模板玩具示例:用户定义的强制转换不适用于复杂类型
- 类模板忽略了用户定义的转换运算符(非模板不忽略)
- 是否可以在 using 声明中引用用户定义的转换模板?
- 从 int 显式转换为用户定义的类 c++
- 使用用户定义的转换运算符推导函数模板参数
- 用户定义的转换不适用于可变参数函数参数?为什么不呢?
- 用户定义的转换顺序(以C++为单位)
- cin 对象如何根据用户需要将字符转换为不同类型的字符?
- 模板类的用户定义运算符上的 C++ 隐式转换