What's the point of iter_swap? - c++

I was just wondering, why would anybody write this:
std::iter_swap(i, k);
instead of this?
std::swap(*i, *k); // saved a few keystrokes!
Then I looked into the implementation of iter_swap, and of course it only uses swap instead of std::swap since we're already in namespace std, anyway. That leads me to the next question:
Why would anybody write this:
using std::swap;
swap(a, b);
instead of this?
std::iter_swap(&a, &b); // saved an entire line of code!
Are there any important differences/issues I am overlooking here?

From the SGI docs (here):
[1] Strictly speaking, iter_swap is redundant. It exists only for technical reasons: in some circumstances, some compilers have difficulty performing the type deduction required to interpret swap(*a, *b).

To answer your second question, the using + swap allows the compiler to use user-defined swap functions that may be more efficient than the default implementation (by using ADL). Explicitly saying std::swap inhibits ADL and any custom swap methods it maybe have been able to find.
As for iter_swap it's presumably there to use in templates and clearly indicate intention rather than a swap that might indicate you expect a pointer.

Related

Which functions in standard C++ library should not be prefixed with std:: when used?

When I program in C++, instead of writing using namespace std;, I generally tend to use std:: prefixed components like std::cout, std::cin etc. But then I came across ADL and why you should use using std::swap;.
Many components of the standard library (within std) call swap in an unqualified manner to allow custom overloads for non-fundamental types to be called instead of this generic version: Custom overloads of swap declared in the same namespace as the type for which they are provided get selected through argument-dependent lookup over this generic version.
But in all sources about ADL, they only mention std::swap. Are there any other functions like this that I have to be beware of when using? Or for all other functions should I use fully qualified name? Or should I use unqualified name for every function in std::?
EDIT: (I wasn't clear when phrasing my initial question. Here is what I exactly intended when I was writing the question.)
Is there any other function in C++ standard libraries that is a popular candidate for ADL based customization much like std::swap, so that when I use them, I have to be cautious to use using std::foo; foo(); form instead of invoking std::foo(); directly?
Suppose you write a library that works with user supplied types. Then you might want to provide a default implementation to foo a bar. But at the same time you want to enable the user to provide their custom implementation because they might know better how to foo their custom bar.
Thats exactly what happens in the standard library with std::swap. The code that relies on ADL is inside libraries, it works with custom types, types it doesn't know until instantiated. And it can provide a default std::swap but at the same time allows the user to provide their own implementation.
In your user-code, when you know the type, then typically you want to know what function is called. Typically you do know if you want to call my::swap or std::swap and you do not need ADL to choose.
That being said, if you have to ask this quesiton then the answer is: Do not make use of ADL. (I know "If you have to ask.." is somewhat silly, but sometimes is applies just too well). Even in library code you do not always want to enable ADL, or allow it as customization. Even if you do write generic code, there might be situations where you need your way to foo a bar without allowing the user to customize it. It really depends.
Short answer: If you want to call std::swap then call std::swap. If you want to call my::swap then call my::swap. If you want to make use of ADL you will know what to do.
PS: There are more examples of ADL that you know but might not be aware of. You almost never use the std:: prefix when you call an operator overload for example. For example std::string operator+(const std::string&,const std::string&). You could write
std::string a,b;
auto c = std::operator+(a,b);
but you don't. You are used to write
auto c = a + b;
And this only works due to ADL.
PPS: Even for std::swap its not right that it "should not be prefixed with std::". As outlined above, sometimes you do want to make use of ADL and sometimes you don't. That decision is not per function, but per use case. If you write code that swaps two objects and for some reason you want to call std::swap and nothing else, then you call std::swap. If you want to make use of ADL then you make use of ADL.

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

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?
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.
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.

Why is std::pair<A,B> not the same as std::tuple<A,B>? (Is there really no way?)

Why is std::pair<A,B> not the same as std::tuple<A,B>? It always felt strange to not be able to just substitute one with the other. They are somewhat convertible, but there are limitations.
I know that std::pair<A,B> is required to have the two data members A first and B second, so it can't be just a type alias of std::tuple<A,B>. But my intuition says that we could specialize std::tuple<A,B>, that is a tuple with exactly two elements, to equal the definition of what the standard requires a std::pair to be. And then alias this to std::pair.
I guess this wouldn't be possible as it is too straight-forward to not to be already thought of, yet it wasn't done in g++'s libstdc++ for example (I didn't look at the source code of other libraries). What would the problem of this definition be? Is it "just" that it would break the standard library's binary compatibility?
You've gotta be careful about things like SFINAE and overloading. For example, the code below is currently well-formed but you would make it illegal:
void f(std::pair<int, int>);
void f(std::tuple<int, int>);
Currently, I can disambiguate between pair and tuple through overload resolution, SFINAE, template specialization, etc. These tools would all become incapable of telling them apart if you make them the same thing. This would break existing code.
There might have been an opportunity to introduce it as part of C++11, but there certainly isn't now.
This is purely historical. std::pair exist since C++98 whereas tuple came after and was initially not part of the standard.
Backward compatibility is the biggest burden for C++ evolution, preventing some nice things to be done easily !
I've not tried this and don't have the bandwidth right now to do so. You could try making a specialisation of std::tuple, derived from a sd::pair. Someone please tell me this won't work or is particularly horrible idea. I suspect you'd run into trouble with accessors.

Is it ok to put "using std::swap;" in a header?

I've read that when you're swaping things in c++, you should always using std::swap;, then call swap unqualified, so it automatically picks the std:: ones for std:: and builtin types, your custom one for custom types, and the templated std:: one for everything else.
So, can I just put using std::swap; in the header that every file includes and not have to worry about it?
I understand that avoiding using in a header is common practice. However, is there a problem with it in this particular case?
The guidance for swap is to using std::swap at the most local scope possible. For certain, one in a header file that's widely included does not meet this requirement. It still pollutes the global namespace in unexpected ways (someone not expecting std::swap will be imported to the global namespace) and should be avoided just like using namespace.
The principle issue here is that you are assuming that people did not write their own swaps that happen to be better matches that do subtly or completely different things to the semantics of std::swap and related friends. For a simple example, consider
void swap(int* a, int* b);
where the contents of the pointers are swapped. Now try to swap a pair of int*. You might think that the pointers are swapped, but instead, surprise! it's the contents that are getting swapped.
Really, the guidance for swap is the same as any other- only using at the most local scope possible and no earlier and definitely not in a header.

Mock the std::move() function to assess its performance impact

I would like to "mock" the std::move() function to assess its (positive) performance impact on a C++ library I have written.
I have used std::move() extensively and I would like to avoid grepping everywhere to remove it. What is the best way to replace it with an identity function? I'm compiling with gcc.
This should "work" but it's actually undefined behaviour:
// Standard library includes must be above.
#define move not_a_move
namespace std {
template<typename T>
typename std::remove_lvalue_reference<T>::type const&
not_a_move(T&& x)
{
return x;
}
}
This won't capture implicit moves or moves done inside the standard library itself. I would recommend just removing all your uses of std::move; it's cleaner and actually allowed. :P
I'm fairly certain there is no way to achieve this short of massacring your own code to remove all the move constructors on the large objects you're wanting to profile. You may also find you would then have problems with passing non rvalue references to functions expecting rvalue references.
So I would suggest not bothering and accept that it's highly likely your code is faster and be satisfied with that.
I actually wanted to try this a year or so ago, and never found a way.