首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在非成员函数上使用delete的意义是什么?

在非成员函数上使用delete的意义是什么?
EN

Stack Overflow用户
提问于 2017-02-20 04:56:03
回答 1查看 1.2K关注 0票数 27

摘自标准20.12 function.objects:

代码语言:javascript
复制
template <class T> reference_wrapper<T> ref(T&) noexcept;
template <class T> reference_wrapper<const T> cref(const T&) noexcept;
template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;

我习惯于在成员函数的上下文中看到=delete。其目的是禁止由编译器提供的操作。例如,使类不可复制或不可移动。

然而,在这种情况下,意图似乎是意图的文档。是这样的吗?是否有其他情况下,在非成员函数上使用=delete是可取的、可取的或不可避免的?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-02-20 05:19:25

据我所知,显式delete自由函数有两个一般原因:拒绝不需要的隐式转换,以及为用户提供更好的错误体验。

拒绝不需要的隐式转换

const的一个有用特性是,临时文件可以绑定到对const的引用。所以这是可行的:

代码语言:javascript
复制
void foo(const int& );
foo(42); // ok

现在,考虑到std::cref().The的目标是通过这个reference_wrapper传递到某个地方,所以我们需要底层引用来保持活动状态。如果我们只有这个重载:

代码语言:javascript
复制
template <class T>
reference_wrapper<const T> cref(const T&) noexcept;

然后我就可以编写std::cref(42)了。这将很好地工作,我将得到一个std::reference_wrapper<const int> -除了它将是一个悬空的引用。这段代码根本不可能正常工作。

为了修复这个明显的bug,我们也有这个重载:

代码语言:javascript
复制
template <class T> void cref(const T&&) = delete;

也就是说,我们显式地删除(或定义为已删除)一个重载,该重载采用任何r值。现在,在执行重载解析时,当我传入一个r值时,第二个重载是首选的,而这个重载是错误的,编译器会通知我们我们的错误(愚蠢的我,我不能做cref(42)!)而不是让我花几个小时在gdb上试图弄清楚为什么我没有对象。

标准库中的其他示例包括:

为用户提供更好的诊断

另一类示例可能是为受约束的函数提供更好的诊断。假设我有一个只对整型有意义的函数:

代码语言:javascript
复制
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
void foo(T);

我试着用非整型调用它:

代码语言:javascript
复制
foo(4.2); // error: no matching function

正如所希望的那样,该操作失败了。但是你得到的错误并不是特别有意义。尤其是在有其他重载的情况下。有了Concepts,这会更好--希望如此,但不一定如此。

但如果我添加反向显式删除重载:

代码语言:javascript
复制
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
void foo(T);

template <typename T, std::enable_if_t<!std::is_integral_v<T>, int> = 0>
void foo(T) = delete;

foo(4.2); // error: use of deleted function

这更加明确和直接。特别是如果foo的作者提供了说明为什么这很重要的注释。基本上,这仍然是SFINAE友好的,同时也提供了直接指示失败的static_assert的好处(然而,如果我们只是static_asserted,我们会得到更清晰的消息,但我们会失去SFINAE友好)。

事实上,N4186的动机是使该注释成为代码本身的一部分(尽管此提议被拒绝)。那篇论文中的例子是:

删除template enable_if_t::value,simd_float> operator+(simd_float,T);template enable_if_t operator+(simd_float,T) =删除;

标准库中的一个示例是用于make_unique<U[N]>std::make_unique()

票数 35
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42332777

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档