本文介绍了如何防止函数模板中的隐式转换?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何定义函数模板以防止隐式转换?

How can I define a function template to prevent implicit conversions?

看来我可以使用非模板函数来防止隐式转换,但不能使用函数模板.

It seems I can prevent implicit conversions using non-template functions but not using function templates.

将转发引用函数模板定义为 = delete 过于激进,因为它会阻止使用非常量左值引用进行调用.

Defining a forwarding reference function template as = delete is too aggressive as it prevents invocation with non-const lvalue references.

将具有 const 右值参数的函数模板定义为 =delete [1]不会阻止隐式转换.

Defining an function template with a const rvalue argument as =delete [1]does not prevent implicit conversions.

将特定类型的右值重载定义为 =delete 是可行的,但我想使用模板来实现这一点.

Defining an rvalue overload for a specific type as =delete works but I'd like to accomplish this with templates.

最小代码示例:

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
}

我的实际用例是变体的散列,如果散列函数没有专门用于所有变体成分,则变体子类型隐式转换回类变体类型将导致无限递归.不过上面的示例代码更清晰.

My real-world use case is hashing of variants where implicit conversion of a variant sub-type back to the variant-like type will cause infinite recursion if the hash function is not specialized for all the variant constituents. The sample code above is clearer though.

[1] 在 为什么我可以阻止原始类型的隐式转换而不是用户定义的类型? 但有一个损坏的代码示例.

[1] Attempted in Why can I prevent implicit conversions for primitives but not user-defined types? but with a broken code example.

推荐答案

以下重载将防止隐式转换:

The following overload will prevent implicit conversions:

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

值重载会毒害为隐式转换设置的重载,因为它将是完全匹配的.

A value-overload poisons the overload set for implicit conversions as it will be an exact match.

template <class T>
void no_conversions(const T&) = delete; // 9

void no_conversions(const B&) {}        // 10

效果一样.

这篇关于如何防止函数模板中的隐式转换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-18 12:53