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?
So is it valid to use
std::sort
for container of tuples with references (i.e. made withstd::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 ofMoveAssignable
andMoveConstructible
.
where MoveAssignable
requires in the expression t = rv
:
The value of
t
is equivalent to the value ofrv
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With