gpt4 book ai didi

c++ - 为什么 std::swap 不能在 Clang/Win 下的 vector 元素上工作?

转载 作者:行者123 更新时间:2023-12-02 04:55:11 25 4
gpt4 key购买 nike

我有这样的代码:

#include <vector>
#include <utility>

int main()
{
std::vector<bool> vb{true, false};
std::swap(vb[0], vb[1]);
}

关于 vector<bool> 理智的争论除此之外,这在以下方面运行良好:

  • Mac 版 Clang
  • Windows 版 Visual Studio
  • Linux 的 GCC

然后我尝试在 Windows 上使用 Clang 构建它,并收到以下错误(已删节):

error: no matching function for call to 'swap'
std::swap(vb[0], vb[1]);
^~~~~~~~~

note: candidate function [with _Ty = std::_Vb_reference<std::_Wrap_alloc<std::allocator<unsigned int> > >, $1 = void] not viable: expects an l-value for 1st argument
inline void swap(_Ty& _Left, _Ty& _Right) _NOEXCEPT_COND(is_nothrow_move_constructible_v<_Ty>&&

令我惊讶的是,不同实现的结果有所不同。

为什么它不能与 Windows 上的 Clang 一起使用?

最佳答案

标准不要求在任何工具链上编译!

首先记住vector<bool>很奇怪,下标它会给你一个名为 std::vector<bool>::reference 的代理类型的临时对象。 ,而不是实际的 bool& .

错误消息告诉您它无法将此临时绑定(bind)到非 const通用 template <typename T> std::swap(T& lhs, T& rhs) 中的左值引用实现。

扩展!

然而,事实证明libstdc++ defines an overload对于 std::swap(std::vector<bool>::reference, std::vector<bool>::reference) ,但这是对该标准的扩展(或者,如果它在那里,我找不到任何证据)。

libc++ does this too .

我猜您仍在使用的 Visual Studio stdlib 实现不会,但雪上加霜 you can bind temporaries to lvalue references在 VS 中(除非您使用一致性模式),所以标准“通用”std::swap在您用 VS 编译器替换更严格的 Clang 编译器之前,该函数一直有效。

因此,您一直依赖它为您工作的所有三个工具链的扩展,而 Windows 上的 Clang 组合是唯一真正表现出严格合规性的组合。

(在我看来,这三个工具链 should have diagnosed this 所以你一直没有发布不可移植的代码。😊)

现在怎么办?

添加您自己的特化 std::swap 可能很诱人。和std::vector<bool>::reference ,但您不能对标准类型执行此操作;事实上,它会与 libstdc++ 和 libc++ 选择作为扩展添加的重载发生冲突。

因此,为了可移植且兼容,您应该更改代码

也许是一个很好的老式:

const bool temp = vb[0];
vb[0] = vb[1];
vb[1] = temp;

或者使用the special static member function that does exactly what you wanted :

std::vector<bool>::swap(vb[0], vb[1]);

也可拼写如下:

vb.swap(vb[0], vb[1]);

关于c++ - 为什么 std::swap 不能在 Clang/Win 下的 vector<bool> 元素上工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58660207/

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