0

Could I exchange two variables using tuple and tie?

int x, y;
....
std::tie(y, x) = std::make_tuple(x, y);
Severin Pappadeux
  • 18,636
  • 3
  • 38
  • 64
  • 4
    Use `std::swap`: http://stackoverflow.com/questions/27671520/magic-in-c-with-this-expression-x-y-x-y-x – nbro Dec 27 '14 at 23:26
  • 1
    `make_tuple` returns a temporary, so what's the benefit? – dyp Dec 27 '14 at 23:27
  • @Bot: No, not at all a duplicate. This tuple is a copy. – MSalters Dec 27 '14 at 23:31
  • fine it is not duplicate but different method. – Irrational Person Dec 27 '14 at 23:32
  • The question in your title doesn't really match the body of your post. The question in your post could have been easily answered by running the included code. Not sure what the problem is here. – Captain Obvlious Dec 27 '14 at 23:34
  • 1
    @CaptainObvlious How would it be obvious that it's undefined behavior by running the code? –  Dec 27 '14 at 23:41
  • 2
    @CaptainObvlious running code cannot prove whether it is undefined behavior or not, PERIOD. Proof by compiler does not work. This case IMHO is a perfect example of allowed RVO, thus at the end copy could be eliminated and we have reading and assignment at the same point, which is AFAIK is undefined behavior – Severin Pappadeux Dec 27 '14 at 23:46
  • 3
    RVO? Where's RVO here? RVO ("copy elision") is applied when you *construct* a new object. E.g. `auto yx = make_tuple(x, y)` and it would only eliminate the copy from the return value of `make_tuple` to `yx`. – dyp Dec 27 '14 at 23:57
  • @nvo I know about swap(), thank you. In your link there was Python idiom mentioned and I thought I could do similar thing in C++. Hence the questions. – Severin Pappadeux Dec 28 '14 at 00:48

1 Answers1

5

std::make_tuple creates a tuple instance, a copy of the arguments, so there's no problem using that to assign back to the original variables.

It is however non-idiomatic and more roundabout than simply using std::swap, i.e. it's not code that one would expect, so I would not do it.

Regarding efficiency, just because that always comes up for such questions, that depends wholly on the compiler: all that can be said is that if it matters, measure.


The std::make_tuple swapping uses a temporary, namely the tuple.

To exhcange the values of two variables of basic integral type, without using a temporary variable, you can just use the old XOR trick:

x ^= y;
y ^= x;    // Sets y = original x value by cancelling the original y bits.
x ^= y;    // Sets x = original y value by cancelling the original x bits.

This is well-defined for unsigned type. It's formally Undefined Behavior for signed type if any of the two values is negative any intermediate value is not representable in the type.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • Can i have my cape and tights back now? :p – Captain Obvlious Dec 27 '14 at 23:36
  • Uh, certainly. I think. – Cheers and hth. - Alf Dec 27 '14 at 23:37
  • But RVO supposed to get rid of the copy, it is a perfect case for RVO, isn't it? – Severin Pappadeux Dec 27 '14 at 23:38
  • @SeverinPappadeux: RVO works nicely here, but dealing with simple types like `int` (two of them) I don't think it improves performance. Rather a good compiler would optimize the whole thing down to a machine code exchange or swap via register temp. – Cheers and hth. - Alf Dec 27 '14 at 23:43
  • For just two values, `swap` might be better (i.e. more idiomatic), but for more, the tie/tuple approach would be better, as `swap` doesn't apply any more. Also, it *is* idiomatic in other languages. If the reader has a haskell/python background they might recognise the idiom. – bitmask Dec 27 '14 at 23:47
  • I just thought that this case IMHO is a perfect example of allowed RVO, thus at the end copy could be eliminated and we have reading and assignment at the same point, which is AFAIK is undefined behavior. There should be a copy somewhere, but how compiler knows to turn off RVO? I agree that for int at the end code would be probably identical to swap() – Severin Pappadeux Dec 27 '14 at 23:50
  • 1
    @SeverinPappadeux: The UB is only for original source code, i.e. for the specification of what should be done. As long as the spec is fine, the compiler is free to use any construct it wants in the generated machine code. That is, RVO is not a source code transformation, it is a way to translate the source code to machine code (namely by passing the address of the storage for the result, to the function, so it can construct the result there directly). – Cheers and hth. - Alf Dec 27 '14 at 23:57
  • The xor trick can really be made to work for any trivially copyable type, can it not? Just make sure you use it on the bytes that make up the objects. –  Dec 27 '14 at 23:58
  • @hvd: I would think with floating point values you can have trap bits that could be turned on by the XOR. Not sure about this and don't have time to check, sorry. And now you got me thinking, C certainly allows trap representations of types larger than `char`, including for `int`. The C++11 standard doesn't specify that the XOR works only on the value representation bits. May be a hole in the standard here. – Cheers and hth. - Alf Dec 28 '14 at 00:02
  • @Cheersandhth.-Alf In general, yes, that could happen, but if the standard doesn't say the behaviour is undefined, and required behaviour can be inferred from the standard, then it's up to the implementation to just make it work. So for floating-point values, the implementation would have to make sure not to load the intermediary result in a floating-point register, only the final result. –  Dec 28 '14 at 00:08
  • @bitmask exactly! I was reading question wrt swap with undefined behavior, and Python was mentioned and I thought that Python idiom might work in C++. Hence the question – Severin Pappadeux Dec 28 '14 at 00:46
  • 2
    I like the typo with letters exchanged in *exhcange* ^^ – Jarod42 Dec 28 '14 at 01:05
  • @Jarod42: Yes, it only works for two distinct variables. It would tend to zero out a single variable. So, should ideally be qualified either by dynamic check or by explanatory text. – Cheers and hth. - Alf Dec 28 '14 at 01:06