C++ 为什么';t std::矢量交换工作<;布尔>;“叮当声/胜利”下的元素?
我有这样的代码:C++ 为什么';t std::矢量交换工作<;布尔>;“叮当声/胜利”下的元素?,c++,visual-studio,clang,c++17,std,C++,Visual Studio,Clang,C++17,Std,我有这样的代码: #include <vector> #include <utility> int main() { std::vector<bool> vb{true, false}; std::swap(vb[0], vb[1]); } #包括 #包括 int main() { 向量vb{true,false}; std::swap(vb[0],vb[1]); } 撇开关于vector是否健全的争论不谈,这在以下方面起到了很好的作用:
#include <vector>
#include <utility>
int main()
{
std::vector<bool> vb{true, false};
std::swap(vb[0], vb[1]);
}
#包括
#包括
int main()
{
向量vb{true,false};
std::swap(vb[0],vb[1]);
}
撇开关于vector
是否健全的争论不谈,这在以下方面起到了很好的作用:
- 麦克的叮当声
- Visual Studio for Windows
- 用于Linux的GCC
错误:调用“swap”时没有匹配的函数
std::swap(vb[0],vb[1]);
^~~~~~~~~
注意:候选函数[with _Ty=std::_Vb_reference,$1=void]不可行:第一个参数需要一个l值
内联无效交换(_Ty&_Left,_Ty&_Right)_NOEXCEPT_COND(不可移动)_move_constructible_v&&
我感到惊讶的是,不同实现的结果有所不同
为什么它不能在Windows上与Clang一起工作?标准不要求在任何工具链上编译它 首先回想一下
vector
很奇怪,订阅它会给您一个名为std::vector::reference
的代理类型的临时对象,而不是实际的bool&
错误消息告诉您,它无法将此临时值绑定到通用模板std::swap(T&lhs,T&rhs)
实现中的非const
左值引用
分机!
然而,事实证明libstdc++forstd::swap(std::vector::reference,std::vector::reference)
,但这是对该标准的扩展(或者,如果在其中,我找不到任何证据)
libc++
我猜您仍在使用的VisualStudio stdlib实现不会这样做,但在VS中会雪上加霜(除非您使用的是一致性模式),因此标准的“generic”,std::swap函数会一直工作,直到您将VS编译器替换为更严格的Clang编译器
因此,您一直依赖于三个工具链上的扩展,这三个工具链对您都有效,而Windows上的叮当声组合是唯一一个真正表现出严格遵从性的组合
(在我看来,这三个工具链使你在这段时间内没有发布不可移植的代码。关于,但不应该这样做,他们被允许这样做。只要他们不破坏一致的代码,他们就可以扩展实现,使破坏的代码“OK”.@NathanOliver:嗯,好吧。不过,他们难道不需要至少诊断一下这些东西的用法吗?@LightnessRaceswithMonica有任何语言禁止这种扩展吗?@Mgetz对不起,我不熟悉所有现存的语言,所以我无法回答,我不确定是否使用了根据本文档格式不正确的扩展t适用。他们添加了一个重载,该重载采用
std::vector::reference
,因此实际上没有任何东西是格式不正确的。对我来说,使用类似char*foo=“bar”
的东西需要进行诊断,因为这是格式不正确的。所以我想需要澄清的是:是操作符[]的结果吗
一个左值?并且std::swap
可以对右值和x值进行操作吗?@Mgetz是的。不。按照这个顺序。这个问题前几天私下里被问到“真实的”,我认为答案是正确的,这很有趣“Clang/Win没有被破坏;代码在整个过程中都被破坏了,但是主流的工具链组合从来没有费心告诉你”写在这里:作为一个参考,这不是在VS2019中编译的/permissive-
(一致性),它通常应该被使用;)@ChrisMM确实!一致性模式关闭是难题的一部分。(尽管我们在调查之前并不知道!)我的回答确实指出:P@ChrisMM不再是了!
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>&&