Lig*_*ica 14 c++ std clang visual-studio c++17
我有这样的代码:
#include <vector>
#include <utility>
int main()
{
std::vector<bool> vb{true, false};
std::swap(vb[0], vb[1]);
}
Run Code Online (Sandbox Code Playgroud)
关于是否理智的争论,在vector<bool>以下方面效果很好:
然后,我尝试在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>&&
Run Code Online (Sandbox Code Playgroud)
对于不同的实现结果,我感到惊讶。
为什么Windows上的Clang不起作用?
Lig*_*ica 15
该标准不需要在任何工具链上进行编译!
首先回忆起来vector<bool>很奇怪,然后下标它给你一个临时的代理类型的对象std::vector<bool>::reference,而不是一个实际的对象bool&。
错误消息告诉您,它不能将此临时绑定绑定到const通用template <typename T> std::swap(T& lhs, T& rhs)实现中的非左值引用。
然而,事实证明,的libstdc ++ 定义过载的std::swap(std::vector<bool>::reference, std::vector<bool>::reference),但是这是一个可扩展标准(或者,如果是在那里,我找不到它的任何证据)。
libc ++ 也这样做。
我猜想您还在使用的Visual Studio stdlib实现并没有实现,但是为了增加伤害,您可以将临时对象绑定到 VS中的左值引用(除非您使用一致性模式),因此std::swap在您将VS编译器替换为更严格的Clang编译器之前,标准的“泛型” 功能才起作用。
结果,您一直依赖于它为您服务的所有三个工具链的扩展,并且Windows上的Clang组合是唯一真正表现出严格合规性的组合。
(我认为,这三个工具链应该已经对此进行了诊断,因此您不会一直都在运送不可移植的代码。)
添加您自己的std::swap和专长可能很吸引人std::vector<bool>::reference,但是您不允许在标准类型中使用;实际上,这将与libstdc ++和libc ++选择添加为扩展的重载冲突。
因此,为了便于移植和合规,您应该更改代码。
也许是一个很好的老式:
const bool temp = vb[0];
vb[0] = vb[1];
vb[1] = temp;
Run Code Online (Sandbox Code Playgroud)
或者使用特殊的静态成员函数来实现您想要的功能:
std::vector<bool>::swap(vb[0], vb[1]);
Run Code Online (Sandbox Code Playgroud)
也可拼写如下:
vb.swap(vb[0], vb[1]);
Run Code Online (Sandbox Code Playgroud)