其他分享
首页 > 其他分享> > c-如何防止函数模板中的隐式转换?

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