What's the difference between std::ranges::swap() and std::swap()?
Asked Answered
M

3

5

In C++20, there are two swap function templates: std::ranges::swap(T&&, U&&) and std::swap(T&, T&).

I just wonder:

What's the difference between they two?

Markson answered 25/7, 2021 at 7:42 Comment(1)
Since you link to cppreference: what is unclear in those pages?Argentic
C
1

In rough terms: std::ranges::swap generalizes std::swap.

  • If T and U are the same, then it's equivalent to invoking std::swap.
  • Otherwise it will swap the arguments as two ranges - if they're ranges.
  • Otherwise it will perform a swap-like procedure with move assignment between the different types T and U.
  • If even that can't happen, it will fail to compile.

See the cppreference page for details.

I must say I find this function to be somewhat confusing and baroque, but then - maybe people more experienced with the range library develop an intuition as to why it makes sense.

Chronicles answered 25/7, 2021 at 7:47 Comment(5)
"baroque" is worth an upvote in itself (although it sneeks an opinion in there).Magda
@TedLyngmo: I said it was my personal impression ("I find").Chronicles
Yes, and I think that it's important that relatively new additions to the library or language is questioned - even here at SO where opinions like this tend to not age well.Magda
@TedLyngmo: Well, you might enjoy my answer to this question then - especially in light of the accepted answer.Chronicles
That's also an Interesting and important view. I did not find it compelling enough for an upvote right now but I will re-read it later.Magda
N
9

std::swap has a problem. It's possible that there is a more efficient swap function that is not in the std namespace. You should enable ADL to find and use that if available and use std::swap otherwise. It's called "std 2-step":

using std::swap;
swap(a, b);

But std::ranges::swap doesn't have this problem and will call the version ADL would have called:

std::ranges::swap(a, b);

Here is a demonstration.

Nonary answered 25/7, 2021 at 8:4 Comment(7)
"It's possible that there is a more efficient swap function that is not in the std namespace" <- Isn't that theoretically true for a huge number of std namespace functions?Chronicles
Can we safely say: std::swap should be totally replaced with std::ranges::swap?Markson
@Markson yes. You should use std::ranges::swap in all new code.Nonary
@Chronicles swap is very often overloaded for custom classes unlike much of the rest of the standard library. If everyone starts using the ranges version, we don't have to keep teaching folks to always remember to enable ADL before using swap in particular. Additionally, ranges also include begin, end, etc which also previously required ADL to work with custom types at all.Nonary
@AyxanHaqverdili: 1. Teaching people to not use std::swap() when they want to swap is not that different then having them incant the "magic spell" of using std::swap. 3. If this is relevant for std::swap, why not std::sort, and all sorts of algorithms too?Chronicles
@Chronicles The problem is that std::swap is very often overloaded while I've never seen std::sort overloaded. This is a very common idiom if you google "std 2-step". This one for instance: what does using std::swap inside the body of a class method implementation mean?.Nonary
@Chronicles no, std::swap is unique in that it's a free function template applicable to approximately every type, that wants to fiddle around in the private parts of classes. std::sort et.al. are defined to use ADL when swapping, they don't need to do the privates-fiddling directly.Sift
C
1

In rough terms: std::ranges::swap generalizes std::swap.

  • If T and U are the same, then it's equivalent to invoking std::swap.
  • Otherwise it will swap the arguments as two ranges - if they're ranges.
  • Otherwise it will perform a swap-like procedure with move assignment between the different types T and U.
  • If even that can't happen, it will fail to compile.

See the cppreference page for details.

I must say I find this function to be somewhat confusing and baroque, but then - maybe people more experienced with the range library develop an intuition as to why it makes sense.

Chronicles answered 25/7, 2021 at 7:47 Comment(5)
"baroque" is worth an upvote in itself (although it sneeks an opinion in there).Magda
@TedLyngmo: I said it was my personal impression ("I find").Chronicles
Yes, and I think that it's important that relatively new additions to the library or language is questioned - even here at SO where opinions like this tend to not age well.Magda
@TedLyngmo: Well, you might enjoy my answer to this question then - especially in light of the accepted answer.Chronicles
That's also an Interesting and important view. I did not find it compelling enough for an upvote right now but I will re-read it later.Magda
C
1

Something not mentioned in the other answers -

Since std::ranges::swap is a niebloid, it represents a single object that can be assigned to a variable or passed to a function.

template< typename T >
void do_something( T& a, T& b, auto function )
{
    function( a, b );
}

do_something( v1, v2, std::ranges::swap ); will compile and work correctly.

do_something( v1, v2, std::swap ); will not compile, because std::swap is both a template and an overloaded one at that.

Chelate answered 1/8 at 13:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.