应该使用我的`swap`重载吗?这是一个libstdc ++(GCC)错误吗?

时间:2012-03-02 19:13:19

标签: c++ gcc clang std

请考虑以下代码:

#include <algorithm>
#include <iostream>
#include <vector>

struct A {
   int val;

   bool operator<(const A& other) const {
      std::cout << "operator\n";
      return val < other.val;
   }
};

void swap(A& a, A& b) {
   std::cout << "foo\n";
   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错误(假设我的标准解释是正确的)?或者我错过了什么?

2 个答案:

答案 0 :(得分:6)

  

C ++ 11的std::sort对迭代器参数提出 ValueSwappable 要求,移动语义而不是其他任何内容,暗示std::sort被“保证”执行交换是否需要移动元素

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

  

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

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

答案 1 :(得分:6)

我发布这个作为答案,因为我没有评论的声誉。

正如@FredOverflow指出的那样,libstdc ++在排序时使用移动构造函数和赋值运算符。但是,我发现奇怪的是它没有将ADL用于pre c ++ 11代码,因此人们可以插入优化的交换函数。