8

In python, I one had to swap values of 2 variables, all you need to do was

x,y=y,x

One can look at it as if the two statements-(x=y) and (y=x) are executed in parallel and not one after another.

Is there any way to achieve the same effect in c++?

NOTE/EDIT:

I am looking to extend this 'parallel effect' (if it exists) to more complicated expressions like
ones,twos= (ones ^ n) ^ ~twos, (ones & n) | (twos & ~n);

This is possible in python, is it possible in c++?

CONCLUSION:

So according to the answer given by leemes and the comments on his answer:

1.You can use boost libraries in C++03 or

2.You can use C++11

to access the std::tie and std::tuple to achieve this 'parallel' effect. As for the present, I mark leemes answer as accepted but I'll still be looking for methods to implement this cool functionality in C++03.

sudeepdino008
  • 3,194
  • 5
  • 39
  • 73

2 Answers2

18

Special case: Swapping the value of two variables

(For the general solution, see below.)

To swap two variable's values in C++, you should always use swap:

using std::swap;
swap(x, y);      // Do NOT say:  std::swap(x, y)    -- Read about Koenig lookup!

Don't bother how it will do it; it will do it very fast. The implementation of the C++ standard library will do its best to optimize this to a single instruction if the processor supports it (but the standard doesn't tell the implementation to do so). For register-only variables, there is for example the x86 instruction xchg which will do it as fast as possible. Don't try to tweak it with some "three xor operations", it won't be any faster. If you're unlucky, it will not be optimized to something like xchg.

The generic swap operation in C++03 introduces a temporary variable and performs three copy constructions. In C++11 there are move-semantics and the objects are rather moved than copied. For your own types, let's say some data structure which holds only a pointer to the actual data, you should optimize this procedure to make it perform in constant time:

  • In C++03, you can either specialize std::swap or implement your own swap function in your namespace (see the two top answers on this question) to optimize swapping: Just swap each member in your class to swap their data. For the data structure example holding just a pointer, just swap the pointers.

  • In C++11, there are the new move semantics, which allow you to implement movement of the data from one to another object, which will result in a very similar behavior. (Move semantics have been introduced for more general problems like swapping two objects: If one object isn't needed anymore, but another one has to be a "copy" of the first, it can simply be moved.) Read about move semantics and move constructor for details.

  • For both C++03 and C++11 there is an alternative way: You can implement implicitly shared data and copy-on-write for heavy classes like data structures. In the example above, where your data structure holds a pointer to the actual data, implement reference counting. When copying the data structure, just increase the reference counter by one. When modifying the data, make sure that it isn't shared (ref count = 1), otherwise "detach" it by copying it only then. This results in a constant-time copy and swap operation.


General case: Multiple arbitrary expressions

For other statements which are not input/output dependent, like (a, b) = (x, y), just write them "as is", and it will run at least perfectly pipelined since they don't have any dependency:

a = x;
b = y;

If they are input/output dependent, like your example in the edit, you can split it up and introduce temporaries. You won't do yourself a favor by trying to solve such with some fancy expression tricks like xor-ing. The compiler knows a lot of tricks for assembler (like xchg), you only know tricks to express such in plain C++ (like xor).

In C++11, there is std::tuple and std::tie allowing you to assign multiple expressions without introducing temporaries (they will be introduced behind the scenes to hold the values stored in the tuple and tries to optimize them either fully away or at least only using registers to hold them if possible):

using std::tie;
using std::make_tuple;
tie(ones, twos) = make_tuple((ones ^ n) ^ ~twos, (ones & n) | (twos & ~n));

Note that the types of the right hand side pair / tuple has to match the target values on the left hand side as conversion isn't implicit here. If you encounter problems, perform a static_cast on the right hand side, tell std::make_tuple the explicit types or just use the constructor for std::tuple requiring explicit types, like:

using std::tie;
using std::tuple;
tie(ones, twos) = tuple<int,int>((ones ^ n) ^ ~twos, (ones & n) | (twos & ~n));
Community
  • 1
  • 1
leemes
  • 44,967
  • 21
  • 135
  • 183
  • Anyone knows if `std::tie` existed before C++11? I'm not sure. I thought it was, but google isn't talkative on this. Is it only available in boost? – leemes Feb 09 '13 at 06:57
  • 1
    No -- C++03 didn't have std::tie or tuples (though Boost implements them in C++03). – Jerry Coffin Feb 09 '13 at 07:04
  • @JerryCoffin Thanks for pointing out; so as expected there is only a nice solution for C++11 unless you want to use boost in C++03. – leemes Feb 09 '13 at 07:06
  • @Mehrdad (edit): Oh, thanks for pointing *this* out. However, you shouldn't name any class `std` (you can, but I'd consider this the worst design ever). Or is there any other possibility for Koenig lookup doing something evil (unwanted) here? – leemes Feb 09 '13 at 07:08
  • The idea here is to allow ADL to do a good thing -- find a version of swap specific to that type if it exits, but use `std::swap` if it doesn't. – Jerry Coffin Feb 09 '13 at 07:11
  • @leemes: I'm not sure what you mean by naming the class `std` -- the class name is irrelevant for argument-dependent (Koenig) lookup. It is *possible* for ADL to perform something "unwanted" here, but if it does, that is the fault of the person who wrote the offending code, not your fault for using it -- `swap` is a well-known function which is always implemented via ADL, so that just means the person isn't playing by the expected rules. In general, you shouldn't try to "defend" against functions which are *expected* to be called via ADL. – user541686 Feb 09 '13 at 07:11
  • @Mehrdad Then I didn't understand it right. I thought it's just specialized for your custom types? (As in the question I just linked when mentioning you can specialize it for your own types.) How will this not work without ADL? As I understood, ADL is used where you reimplement something in some namespace, let's say `namespace A`, so it becomes `A::swap`. The compiler will use this is possible and only fall back to `std::swap`. But why not just specializing `std::swap` for `A::some_type`? – leemes Feb 09 '13 at 07:16
  • @leemes: Specialization is different from ADL, but yes, it can be used for a similar purpose. If you want to implement `swap`, you have two choices -- you can *either* specialize `std::swap` (which means doing so *inside* the `std` namespace), *or* you implement a function which can be called via ADL (but you shouldn't do both!). People do the latter more often. But if you want to actually *call* the appropriate `swap`, then you must account for either case, by saying `using std::swap;` to allow for specialization, and then saying `swap(a, b)` to allow the correct function to be called. – user541686 Feb 09 '13 at 07:18
  • @Mehrdad Understood; thanks. Can you please review the changes in my last edit? – leemes Feb 09 '13 at 07:23
  • @leemes: Sure, yes! It looks fine. :) – user541686 Feb 09 '13 at 07:28
  • @leemes: No problem! Also, other things to be aware of: if you have inheritance going on, then how you usually deal with it is by defining the ADL version of `swap(T a, T b)` and having it call `a.swap(b)`. Then you define a *method* called `swap` inside the class, and have it call `this->BaseClass::swap(b)` as necessary. Another final note: Prior to C++11, you were often *forced* to use ADL instead of specialization, because you can't partially specialize a function (like `std::swap`) in C++03. – user541686 Feb 09 '13 at 07:31
  • +1 - `std::tie` was the first thing that sprang to my mind, too. – Christian Rau Feb 09 '13 at 10:01
  • 2
    "Per default, I think the generic implementation has to introduce a temporary and performs three copy constructions." Not any longer in C++11: for movable types the move constructor/move assignment operators are used by default. This makes many custom implementations of swap irrelevant. – Matthieu M. Feb 09 '13 at 10:54
  • @MatthieuM. +1 In fact the types that profited from an efficient custom `swap` implementation in C++03 are usually also the ones that now have an efficient move operation, anyway. – Christian Rau Feb 09 '13 at 15:41
  • @MatthieuM. and ChristianRau: Thank you for your input. I extended the answer and also added an alternative (but more complicated) solution for C++03 and C++11. – leemes Feb 10 '13 at 06:39
  • You should use `shared_ptr` instead of implementing your own reference-counting scheme. – Neil G Feb 11 '13 at 03:33
0

If x and y are plain integers, there are various fast tricks to swap them in one line:

http://cpptruths.blogspot.com/2006/04/swapping-two-integers-in-one-liner.html

Forhad Ahmed
  • 1,761
  • 13
  • 18
  • 1
    Most of those cause undefined behaviour, and even if they didn't, would still be no faster than the three line example. – Carl Norum Feb 09 '13 at 06:42
  • 5
    Tricks are nice for educational purposes, code quizzes and stuff, but for real code use something like `std::swap`. – leemes Feb 09 '13 at 06:45