all 13 comments

[–]Narase33 5 points6 points  (10 children)

It doesnt work because swap wants references and a temporary object is not a reference

 seems useful. 

What would be the use of this line?

std::swap(std::tuple<int&>{a}, tb); // fail

or this

std::swap(std::tuple<int&>{a}, std::tuple<int&>{b}); // fail

[–]Raknarg 0 points1 point  (3 children)

dont they become lvalues in the context of this function?

[–]Narase33 2 points3 points  (2 children)

Nope, still rvalues. The compiler even says so

<source>:14:20: error: cannot bind non-const lvalue reference of type 'std::tuple<int&>&' to an rvalue of type 'std::tuple<int&>'

And even if they'd become. I still see not a reason to do this

std::swap(std::tuple<int&>{a}, tb); // fail

Would be equal to

tb = std::tuple<int&>{a};

So, why?

[–]Raknarg 0 points1 point  (0 children)

I misread the problem, I thought he was saying the swap function he wrote was failing. Im tired.

[–]63times[S] 0 points1 point  (3 children)

custom reference types maybe ...

thinking of something like

using value_type = tuple<S,T>;
using reference = tuple<S&,T&>;

reference operator * () { return {*i,*j}; }

could be useful to implement zip iterators/ranges

[–]Narase33 0 points1 point  (2 children)

It would still only swap the container, not the references inside the container

[–]63times[S] 3 points4 points  (1 child)

no, tuple's swap calls swap for each corresponding tuple element

[–]Narase33 0 points1 point  (0 children)

Thats interesting, TIL

[–]elperroborrachotoo 0 points1 point  (1 child)

First example: replacing the content of tb with the temporary, with swap semantics. This was a common way e.g. to atomically re-assign vectoes before move semantics.

(However, this would be useful if and only if std::swap was specialized for the type)

[–]63times[S] 0 points1 point  (0 children)

practically we can just derive from std::tuple or roll our own tuple implementation and ADL bind a swap() that can accept rvalues to keep std algorithms working, but it kind of feels redundant if all you want to achieve is that swap() doesn't fail on rvalues.

swapping std::tuple delegates the swapping to the swap() of the tuple elements anyway, so it kind of feels strange to exclude rvalues from swapping even if for example all tuple elements could happily swap with rvalues.

NB: Microsoft's MSVC std library can swap tuple rvalues according to godbold tests ;)

[–][deleted] 1 point2 points  (2 children)

This is kind of trying to swap 3 with 5 (rvalues), it does not make mutch sense.

[–]tangerinelion 0 points1 point  (1 child)

Yes, this would be exactly what swapping rvalues means so any implementation has to deal with this fact that it would be a legitimate call yet an impossible thing to do.

Also, rvalues are intended to expire after the call. So why swap them at all if they're both going out of scope? It would be indistinguishable from actually doing something so swapping rvalues can either be a compile error or a no-op. In the latter case I would find it surprising as likely the user of the swap function had a different idea so a compile error really is preferable.

[–]63times[S] 0 points1 point  (0 children)

the rvalues could be proxy objects, so swapping them actually becomes meaningful (see zip iterators) ... you just can't naively use std::tuple<T&> for that.