Reading C++ named requirements: Swappable I've come across the following note
It is unspecified whether
<utility>
is actually included when the standard library functions perform the swap, so the user-provided swap() should not expect it to be included.
Suppose I have a user-defined type class Foo
with a user-provided swap()
. I'd like to use a Standard Library algorithm for my class Foo
that performs a swap with
using std::swap;
swap(arg1, arg2);
as described in the above-mentioned cppreference article, and the file that I have to
#include
to use this algorithm does NOT #include <utility>
.
If I relied on functionality provided by <utility>
in my swap()
, how could this lead to a problem? I'd have to #include <utility>
myself in the file that defines my swap()
. The scenario should be similar to the following: I have a file that #includes
my class Foo
with my user-provided swap()
and the header for the algorithm that I use. Consequently, there should never be an issue regarding whether the algorithm does #include <utility>
or not.
I might have misunderstandings revolving around how #include
and compilation could interact with each other in some different scenarios. Which situation could potentially lead to compilation issues here?
utility (C++) utility is a header file in the C++ Standard Library. This file has two key components: rel_ops , a namespace containing set of templates which define default behavior for the relational operators != , > , <= , and >= between objects of the same type, based on user-defined operators == and < .
IBM® Integration Bus provides some additional utilities that user-defined nodes and parsers can use. These utilities belong to the following categories: Exception handling and logging. Character representation handling.
The function std::swap() is a built-in function in the C++ Standard Template Library (STL) which swaps the value of two variables.
It is not atomic. Atomic operations are not cheap and 99% of the time you do not need the atomicity. There are (IIRC) some other means to get atomic operations but std::swap() is not one of them.
Let's try to understand the note you quoted from cppreference.
It is unspecified whether
<utility>
is actually included when the standard library functions perform the swap, so the user-provided swap() should not expect it to be included.
E.g., std::sort
may perform the swap. To use std::sort
, you need to include <algorithm>
. The statement basically says, despite this, <algorithm>
may not have <utility>
included. It follows that below code may be problematic.
#include <algorithm>
int main() {
int arr[] = { 4, 1, 7 };
std::sort(arr, arr + 3);
std::swap(arr[0], arr[1]); // may error out here
}
This is counter-intuitive, for std::sort
performs std::swap
internally itself. To stay on the safe side, always explicitly include <utility>
if you need std::swap
. Don't assume that some other standard library headers that use std::swap
themselves have <utility>
included for you. Following code should always work, while #include <utility>
seems unnecessary at first sight.
#include <algorithm>
#include <utility>
int main() {
int arr[] = { 4, 1, 7 };
std::sort(arr, arr + 3);
std::swap(arr[0], arr[1]);
}
The short answer would be that the without explicit #include <utility>
, there is no guarantee of std::swap
fallback in case there is no custom swap
for Foo
s; leading to compilation errors.
If there is using std::swap;
statement somewhere in the code - yours, or inside the algorithm - then the std::swap
function must already be included, otherwise you get a compilation error.
What the cppreference points at is that there is no guarantee that std::foo_algorithm
will include <utility>
and use using std::swap;
construct before it calls swap(a,b)
. Note that it uses unqualified name for the swap as it should.
This means that if your class depends on presence of std::swap
, because it lacks any custom swap
function, then calling std::foo_algorithm
might result in compilation errors saying there is no appropriate swap(Foo&,Foo&)
function, due to std::swap
not being automatically included. The easy fix is to place #include <utility>
before #include <foo_algorithm>
.
But, if you have a custom swap and the algorithm can find it (either because it has been either included directly in the current namespace or ADL kicks in), everything will compile just fine. Unrelated to that, your swap should be using the using std::swap; swap(a,b);
construct anyway, so std::swap
is likely always present if your swap
is.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With