【问题标题】:What's the difference between =delete for templates and just using explicit?模板的 =delete 和仅使用显式有什么区别?
【发布时间】:2021-10-25 02:49:08
【问题描述】:

我在阅读Explicitly defaulted and deleted special member functions,看到为了只用double 调用函数f 并避免隐式转换,可以这样写(from the same page):

struct OnlyDouble
{
    void f(double d);
    template<class T> void f(T) = delete;
};

有理由写上面的代码而不是下面的代码吗?

struct OnlyDouble
{
    explicit void f(double d);
};

有什么不同,还是有一些我不知道的额外行为?

【问题讨论】:

  • 第二个sn-p没有编译......
  • explicit 没有按照你的想法做。它只适用于构造函数,并且你的成员函数f 不是构造函数。 f - 在您的第二个示例中 - 仍然允许将其参数 d 从可以隐式转换为 double 的任何内容隐式转换,例如,f(1.3f)f(17) 仍然可以工作。
  • 在第一个代码中,f() 只能用double 来调用,任何其他类型都会产生错误。在第二个代码中(如果已编译),f() 可以用任何可转换为double 的类型调用。 explicit 只能用于构造函数、转换运算符和推导指南,f() 不是这些。
  • 谢谢。有人可以写一个答案以便我接受和投票吗?

标签: c++ c++11 c++17 c++14


【解决方案1】:

两件事:

  1. explicit 对函数无效,因此 explicit void f(double); 无法编译。
  2. explicit 不会阻止参数的隐式转换。

也就是说,即使比较是在:

struct OnlyDouble
{
    OnlyDouble(double d);
    template<class T> OnlyDouble(T) = delete;
};

struct OnlyDouble
{
    explicit OnlyDouble(double d);
};

你说得对,两者都会出错:

OnlyDouble od = 42;

但下面的第一个格式不正确,第二个格式正确:

OnlyDouble od(42);

【讨论】:

  • 如果explicit 不能阻止隐式转换,那么2 会做什么?
  • @heretoinfinity:它可以防止对 constructor 的隐式调用。
  • @heretoinfinity 在单参数情况下,explicit 防止从参数直接隐式转换为类型。例如,给定void foo(OnlyDouble);foo(42) 需要将42 隐式转换为OnlyDoubleexplicit 阻止了这种转换。在多参数情况下,它会阻止大括号初始化列表作为参数传递。例如,给定struct S { explicit S(int, int); };void foo(S);foo({1, 2})explicit 是非良构的,但在没有explicit 时是良构的。
猜你喜欢
  • 1970-01-01
  • 2010-11-25
  • 2023-03-30
  • 2023-02-20
  • 2022-01-03
  • 2010-10-14
  • 2020-07-14
  • 2010-09-13
相关资源
最近更新 更多