我可以对引用元组的向量进行排序吗?

时间:2016-05-10 15:12:52

标签: sorting c++11 tuples

以下代码:

std::vector<std::tuple<int&>> v;
int a = 5; v.emplace_back(a);
int b = 4; v.emplace_back(b);
int c = 3; v.emplace_back(c);
int d = 2; v.emplace_back(d);
int e = 1; v.emplace_back(e);
std::sort(std::begin(v), std::end(v));

使用gcc / libstdc ++编译vs clang / libc ++ binary会产生不同的结果。

对于gcc/libstdc++,一个元素被复制到所有其他引用。

5 4 3 2 1 
5 5 5 5 5

首先我认为clang/libc++按预期行为 但它最多只能处理一个向量中的5个元素(因为小容器有一个特例)。

5 4 3 2 1 
1 2 3 4 5 

传递更多元素时,结果类似于gcc。

5 4 3 2 1 0 
3 4 5 5 5 5

使用std::sort对带引用的元组容器(即使用std::tie进行排序,结构的子集)是否有效? 如果没有,我应该期待任何警告吗?

1 个答案:

答案 0 :(得分:6)

  

使用std::sort对带引用的元组容器(即使用std::tie进行排序,结构的子集)是否有效?如果没有,我应该期待任何警告吗?

不,不。 std::sort()的类型要求之一是:

  
      
  • 解除引用的RandomIt类型必须符合MoveAssignableMoveConstructible的要求。
  •   

表达式t = rv中需要MoveAssignable

  

t的值等效与分配前rv的值相同。

std::tuple<int&>不是MoveAssignable,因为int&不是MoveAssignable。如果您只是:

int& ra = a;
int& rb = b;

ra = std::move(rb);

ra的值不等于rb的先前值。 ra仍然引用a,它不会更改为引用b - 实际更改的内容是a的值。

由于我们的类型不符合std::sort()的前提条件,因此std::sort()调用的结果只是未定义的行为。

请注意,可以std::vector<std::tuple<std::reference_wrapper<int>>>进行排序,因为std::reference_wrapper是MoveAssignable。

另请注意,这可能让人想起无法按照旧的Herb Sutter articleauto_ptr的容器进行排序。