gpt4 book ai didi

c++ - 在非成员函数上使用 delete 有什么意义?

转载 作者:IT老高 更新时间:2023-10-28 12:53:45 25 4
gpt4 key购买 nike

摘自标准 20.12 [function.objects]:

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 是可取、可取或不可避免的吗?

最佳答案

我知道明确delete 的原因有两个。免费功能:拒绝不需要的隐式转换,为用户提供更好的错误体验。


拒绝不需要的隐式转换

const 的一个有用功能|临时人员可以绑定(bind)到对 const 的引用吗? .所以这行得通:

void foo(const int& );
foo(42); // ok

那个临时的42绑定(bind)到函数的引用参数,并且它的生命周期与该引用参数绑定(bind)。

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

template <class T>
reference_wrapper<const T> cref(const T&) noexcept;

然后我可以写std::cref(42) .那会很好用,我会返回 std::reference_wrapper<const int> - 除非它是一个悬空的引用。该代码不可能工作。

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

template <class T> void cref(const T&&) = delete;

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

标准库中的其他示例有:

为用户提供更好的诊断

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

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

我尝试用非整数类型调用它:

foo(4.2); // error: no matching function

根据需要,这会失败。但是你得到的错误并不是很有意义。特别是如果有其他重载。有了概念画板,这会更好——希望,但不一定。

但是如果我添加相反的显式删除重载:

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_assert 编辑,我们会得到更清晰的信息,但我们会失去对 SFINAE 的友好性)。

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

template <typename T>
enable_if_t<has_compatible_vector_size<simd_float, T>::value, simd_float>
operator+(simd_float, T);

template <typename T>
enable_if_t<!has_compatible_vector_size<simd_float, T>::value, simd_float>
operator+(simd_float, T) = delete;

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

关于c++ - 在非成员函数上使用 delete 有什么意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42332777/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com