高完整性C ++标准建议可以删除函数的rvalue参数,从而防止隐式转换。
我发现原语和用户定义类型的行为非常不同。
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).
}
为什么删除的rvalue重载会阻止隐式转换为int而不是从一个用户定义的类型转换为另一个?
答案 0 :(得分:2)
高完整性C ++标准建议使用rvalue参数 可以删除函数,从而防止隐式转换。
不,只有转发引用重载会对重载集中的所有其他重载禁用ICS (Implicit Conversion Sequence)。将其作为转发参考,并see ICS disabled (Coliru Link)
template <class T>
void foo(const T&&) = delete; // introduces a qualification match
以上代码为重载添加了限定匹配。因此,ICS仍然在发挥作用。
为什么foo(3.3)
失败是因为3.3
是double
类型的 prvalue ,它与rvalue重载匹配比转换为int
更好。因为资格匹配是ranked better而不是转换匹配
答案 1 :(得分:1)
有3种可能的重载
2更好匹配(模板(非完全匹配)与常规方法(一个用户定义转换))。
您可以查看http://en.cppreference.com/w/cpp/language/overload_resolution 查看所需的一整套规则
答案 2 :(得分:1)
在您的代码中,用户定义类型和基本类型之间的处理没有区别。这两行的行为之间的区别:
foo(a);
foo(3.3);
a
是左值,3.3
是左值。 rvalue参数匹配您的重载1
(只接受rvalues),而lvalue参数不匹配。
如果您尝试使用rvalue参数调用foo<A>
,它也会匹配1
并失败,例如foo(A{});
。