请考虑以下代码:
#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 ++没有。
答案 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代码,因此人们可以插入优化的交换函数。