c-如何防止函数模板中的隐式转换?
作者:互联网
如何定义函数模板以防止隐式转换?
看来我可以防止使用非模板函数但不能使用函数模板进行隐式转换.
将转发引用功能模板定义为= delete过于激进,因为它阻止了使用非常量左值引用的调用.
用const rvalue参数将函数模板定义为= delete [1]
不会阻止隐式转换.
通过= delete可以为特定类型定义右值重载,但是我想使用模板来完成.
最少的代码示例:
struct A {};
struct B {
B() = default;
B(const A&) {}
};
// Delete const rvalue reference.
template <class T>
void t_no_rvalue(const T&&) = delete; // 1
void t_no_rvalue(const B&) {} // 2
// Delete forwarding reference.
template <class T>
void t_no_fwd_ref(T&&) = delete; // 3
void t_no_fwd_ref(const B&) {} // 4
// (non-template) Delete const rvalue reference.
void no_rvalue(const B&&) = delete; // 5
void no_rvalue(const B&) {} // 6
int main(int argc, char* argv[]) {
A a;
B b;
// Undesired behaviour, implicit conversion allowed.
t_no_rvalue(a); // resolves to 2
t_no_rvalue(b); // resolves to 2
// Undesired behaviour, invocation with non-const reference disallowed.
t_no_fwd_ref(a); // resolves to 3
t_no_fwd_ref(b); // resolves to 3
// Desired behaviour.
no_rvalue(a); // resolves to 5
no_rvalue(b); // resolves to 6
}
我在现实世界中的用例是变体的散列,其中如果散列函数不专用于所有变体成分,则将变体子类型隐式转换回类似变体的类型将导致无限递归.上面的示例代码更加清晰.
[1]在Why can I prevent implicit conversions for primitives but not user-defined types?中尝试过,但代码示例已损坏.
解决方法:
以下重载将防止隐式转换:
template <class T>
void no_conversions(T) = delete; // 7
void no_conversions(const B&) {} // 8
并导致:
// Requested behaviour.
no_conversions(a); // resolves to 7
no_conversions(b); // resolves to 8
值超载会使隐式转换的超载集中毒,因为这将是精确匹配.
编辑:
template <class T>
void no_conversions(const T&) = delete; // 9
void no_conversions(const B&) {} // 10
效果也一样.
标签:c,templates,overload-resolution 来源: https://codeday.me/bug/20191011/1889621.html