Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I sort vector of tuple of references?

When following code:

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));

is compiled with gcc/libstdc++ vs clang/libc++ binary gives different results.

For gcc/libstdc++ one element is copied to all the other references.

5 4 3 2 1 
5 5 5 5 5

First I thought that clang/libc++ behaves as expected but it only works up to 5 elements in a vector (cause there is a special case for small containers).

5 4 3 2 1 
1 2 3 4 5 

When passing more elements result is similar to gcc.

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

So is it valid to use std::sort for container of tuples with references (i.e. made with std::tie, sorting subset of struct)? If not, should I expect any warnings?

like image 380
Karol Wozniak Avatar asked May 10 '16 15:05

Karol Wozniak


1 Answers

So is it valid to use std::sort for container of tuples with references (i.e. made with std::tie, sorting subset of struct)? If not, should I expect any warnings?

No, and no. One of the type requirements on std::sort() is that:

  • The type of dereferenced RandomIt must meet the requirements of MoveAssignable and MoveConstructible.

where MoveAssignable requires in the expression t = rv:

The value of t is equivalent to the value of rv before the assignment.

But std::tuple<int&> isn't MoveAssignable because int& isn't MoveAssignable. If you simply have:

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

ra = std::move(rb);

The value of ra isn't equivalent to the prior value of rb. ra still refers to a, it does not change to refer to b - what actually changed was the value of a.

Since our type doesn't meet the precondition of std::sort(), the result of the std::sort() call is just undefined behavior.


Note that you could sort a std::vector<std::tuple<std::reference_wrapper<int>>> though, because std::reference_wrapper is MoveAssignable.

Note also that this is reminiscent of not being able to sort a container of auto_ptr, per an old Herb Sutter article.

like image 155
Barry Avatar answered Jan 02 '23 18:01

Barry