Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

<utility> not necessarily included when swap() is performed - How can this become a problem?

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?

like image 549
Ruperrrt Avatar asked Oct 05 '21 11:10

Ruperrrt


People also ask

What does include utility do c++?

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

What is utility in c language?

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.

What library is swap in C++?

The function std::swap() is a built-in function in the C++ Standard Template Library (STL) which swaps the value of two variables.

Is STD swap Atomic?

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.


Video Answer


2 Answers

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]);
}
like image 149
Lingxi Avatar answered Nov 15 '22 09:11

Lingxi


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 Foos; 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.

like image 30
Quimby Avatar answered Nov 15 '22 09:11

Quimby