为什么 std::swap 不适用于<bool> Clang/Win(英语:Clang/Win)下的矢量元素?
Why doesn't std::swap work on vector<bool> elements under Clang/Win?
我有这样的代码:
#include <vector>
#include <utility>
int main()
{
std::vector<bool> vb{true, false};
std::swap(vb[0], vb[1]);
}
除了关于vector<bool>
的健全性的争论之外,这在上运行得很好
- Clang for Mac
- Visual Studio for Windows
- GCC for Linux
然后我尝试在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&
。
错误消息告诉您,它无法将此临时绑定到通用template <typename T> std::swap(T& lhs, T& rhs)
实现中的非const
左值引用。
扩展
然而,事实证明,libstdc++为std::swap(std::vector<bool>::reference, std::vector<bool>::reference)
定义了一个重载,但这是对标准的扩展(或者,如果它在那里,我找不到任何证据(。
libc++也能做到这一点。
我猜您仍在使用的Visual Studio stdlib实现没有,但雪上加霜的是,您可以将临时库绑定到VS中的左值引用(除非您使用一致性模式(,因此标准的"泛型"std::swap
函数可以工作,直到您用VS编译器替换更严格的Clang编译器。
因此,您一直依赖于它为您工作的所有三个工具链上的扩展,而Clang on Windows组合是唯一一个真正表现出严格合规性的组合。
(在我看来,这三个工具链应该已经诊断出了这一点,这样你就不会一直发布不可移植的代码。 )
现在怎么办
添加您自己的std::swap
和std::vector<bool>::reference
专业化可能很诱人,但对于标准类型,您不允许这样做;事实上,这将与libstdc++和libc++选择作为扩展添加的重载相冲突。
因此,为了便于移植和兼容,您应该更改代码。
也许是一个不错的老式:
const bool temp = vb[0];
vb[0] = vb[1];
vb[1] = temp;
或者使用特殊的静态成员函数,它可以做你想要的事情:
std::vector<bool>::swap(vb[0], vb[1]);
也可拼写如下:
vb.swap(vb[0], vb[1]);
- 奇怪的结构&GCC&clang(void*返回类型)
- 数据成员SFINAE的C++17测试:gcc vs clang
- 当我编译webrtc服务器时,Windows上只支持clang-cl
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 我可以将一个用clang c++11编译的对象与另一个用c++17编译的对象链接起来吗
- Clang bug?使用指针作为模板参数
- clang整洁10忽略了我的NOLINT命令
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 在clang++预处理器中确定gcc工具链版本
- 为什么 Clang 不允许"and"作为函数名称?
- 带有 -stdlib=libc++ 的 clang++ 9.0.1 找不到<optional>
- clang格式:宏的缩进
- CLANG 编译器 说:变量"PTR"可能未初始化
- clang格式:禁用排序包含
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- gcc和clang在表达式是否为常量求值的问题上存在分歧
- 循环展开 - G++ 与 Clang++
- 如何使用Clang/GCC在Mac上为C/C++设置VSCode
- 一位朋友将模板函数缩写为clang和gcc
- 为什么 std::swap 不适用于<bool> Clang/Win(英语:Clang/Win)下的矢量元素?