执行 swap() 时不一定包含 <utility> - 这怎么会成为问题呢?

Rup*_*rrt 8 c++ stl header-files

阅读C++ 命名需求:可交换我遇到了以下注释

当标准库函数执行交换时,未指定是否<utility>实际包含它,因此用户提供的 swap() 不应期望包含它。

假设我有一个用户定义的类型class Foo和用户提供的swap(). 我想使用标准库算法来class Foo执行交换

using std::swap;
swap(arg1, arg2);
Run Code Online (Sandbox Code Playgroud)

如上述 cppreference 文章中所述,并且我必须 #include使用此算法的文件没有#include <utility>

如果我依赖<utility>my 中提供的功能swap(),这怎么会导致问题呢?我必须#include <utility>自己在定义我的swap(). 该场景应类似于以下内容:我有一个文件,其中#includes包含class Foo用户提供的文件swap()以及我使用的算法的标头。因此,永远不存在算法是否#include <utility>这样做的问题。

#include我可能对编译和编译在某些不同场景中如何相互作用存在误解。哪种情况可能会导致这里出现编译问题?

Lin*_*gxi 5

让我们尝试理解您从 cppreference 引用的注释。

当标准库函数执行交换时,未指定是否<utility>实际包含它,因此用户提供的 swap() 不应期望包含它。

例如,std::sort可以执行交换。要使用std::sort,您需要包含<algorithm>. 该声明基本上说,尽管如此,<algorithm>可能并未<utility>包括在内。由此可见,下面的代码可能有问题。

#include <algorithm>

int main() {
  int arr[] = { 4, 1, 7 };
  std::sort(arr, arr + 3);
  std::swap(arr[0], arr[1]); // may error out here
}
Run Code Online (Sandbox Code Playgroud)

这是违反直觉的,因为它本身在内部std::sort执行std::swap为了安全起见,<utility>如果需要,请始终明确包含std::swap. 不要假设已经为您包含了一些使用std::swap自身的其他标准库头文件。<utility>以下代码应该始终有效,但#include <utility>乍一看似乎没有必要。

#include <algorithm>
#include <utility>

int main() {
  int arr[] = { 4, 1, 7 };
  std::sort(arr, arr + 3);
  std::swap(arr[0], arr[1]);
}
Run Code Online (Sandbox Code Playgroud)

  • 发现。尽管使用 `std::swap` 几乎肯定*会*安全,即使不包括 `&lt;utility&gt;`,因为 `std::sort` 需要定义它才能使用它。更现实的失败情况是使用“&lt;utility&gt;”中定义的任何*其他*函数,例如“std::exchange”。 (2认同)
  • @KonradRudolph,实现可以在“std”之外的其他名称空间中自由定义“swap”,只要将“&lt;utility&gt;”“using”到“std”中即可。这与 `&lt;algorithm&gt;` 是分开的,确保它位于 `sort` 使用的重载集中 (2认同)