为什么我可以阻止基元的隐式转换而不是用户定义的类型?
Why can I prevent implicit conversions for primitives but not user-defined types?
高完整性 C++ 标准建议可以删除函数的右值参数,从而防止隐式转换。
我发现基本类型和用户定义类型的行为非常不同。
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 而不是从一种用户定义类型到另一种用户定义类型?
有 3 种可能的重载
- 1 个可行。
- 2 可行
- 3 不是
2 是更好的匹配(模板(非精确匹配)与常规方法(使用一个用户定义的转换))。
你可以看看http://en.cppreference.com/w/cpp/language/overload_resolution
查看所需的完整规则集
The High Integrity C++ Standards suggest that rvalue arguments to
functions can be deleted thus preventing implicit conversions.
不,只有 转发引用 过载禁用 ICS (Implicit Conversion Sequence) for all other overloads in the overload set. Make it a forwarding reference, and 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 与转换为int
。因为 资格匹配 比 转换匹配
ranked better
在您的代码中,用户定义类型和原始类型之间的处理方式没有区别。这两行行为的区别:
foo(a);
foo(3.3);
就是a
是左值,3.3
是右值。右值参数匹配您的重载 1
(仅接受右值),左值参数不匹配。
如果您尝试使用右值参数调用 foo<A>
,它也会匹配 1
并失败,例如foo(A{});
.
高完整性 C++ 标准建议可以删除函数的右值参数,从而防止隐式转换。
我发现基本类型和用户定义类型的行为非常不同。
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 而不是从一种用户定义类型到另一种用户定义类型?
有 3 种可能的重载
- 1 个可行。
- 2 可行
- 3 不是
2 是更好的匹配(模板(非精确匹配)与常规方法(使用一个用户定义的转换))。
你可以看看http://en.cppreference.com/w/cpp/language/overload_resolution 查看所需的完整规则集
The High Integrity C++ Standards suggest that rvalue arguments to functions can be deleted thus preventing implicit conversions.
不,只有 转发引用 过载禁用 ICS (Implicit Conversion Sequence) for all other overloads in the overload set. Make it a forwarding reference, and 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 与转换为int
。因为 资格匹配 比 转换匹配
在您的代码中,用户定义类型和原始类型之间的处理方式没有区别。这两行行为的区别:
foo(a);
foo(3.3);
就是a
是左值,3.3
是右值。右值参数匹配您的重载 1
(仅接受右值),左值参数不匹配。
如果您尝试使用右值参数调用 foo<A>
,它也会匹配 1
并失败,例如foo(A{});
.