我的“交换”过载应该被使用吗?这是一个libstdc++(GCC)错误吗

Is my `swap` overload supposed to be used? Is this a libstdc++ (GCC) bug?

本文关键字:交换 一个 错误 GCC libstdc++ 我的      更新时间:2023-10-16

考虑以下代码:

#include <algorithm>
#include <iostream>
#include <vector>
struct A {
   int val;
   bool operator<(const A& other) const {
      std::cout << "operatorn";
      return val < other.val;
   }
};
void swap(A& a, A& b) {
   std::cout << "foon";
   std::swap(a.val, b.val);
}
int main()
{
   std::vector<A> a(2);
   a[0].val = 10;
   a[1].val = -1;
   std::sort(a.begin(), a.end());
}

C++11的std::sort在迭代器参数、移动语义和其他方面都提出了ValueSwappable要求,这意味着如果元素需要四处移动,std::sort"保证"执行交换。17.6.3.2/3建议,在这种情况下,我的过载肯定应该被选择。

  • 这是正确的吗

clang 3.1 SVN的libc++选择了我的swap(也就是说,我看到了"foo");GCC 4.6.3的libstdc++没有。

  • 这是GCC错误吗(假设我的标准解释是正确的)?还是我错过了什么

C++11的std::sort在迭代器参数、移动语义和其他方面都提出了ValueSwappable要求,这意味着如果元素需要四处移动,std::sort"保证"执行交换。

我看不出有什么保证。谁说std::sort不能使用移动语义而不是交换?事实上,在浏览了逐字逐句规范的标准后,我相信这正是发生的事情:

要求:RandomAccessIterator应满足ValueSwappable(17.6.3.2)的要求。*first的类型应满足MoveConstructible(表20)和MoveAssignable(表22)的要求

请注意,迭代器应为ValueSwappable,而不是它们所指向的元素。

我把这作为一个答案发布,因为我没有声誉可以评论。

正如@FredOverflow所指出的,libstdc++在排序时使用移动构造函数和赋值运算符。然而,我觉得奇怪的是,它没有将ADL用于c++11之前的代码,这样人们就可以插入优化的交换函数。

相关文章: