不合格的 sort()——为什么在 std::vector 上使用而不是在 std::array 上编译,哪个编译器是正确的?

Guy*_*ton 11 c++ c++17

当调用std::sort()a 时std::array

#include <vector>
#include <array>
#include <algorithm>

int main() {
    std::vector<int> foo{4, 1, 2, 3};
    sort(begin(foo), end(foo));

    std::array<int, 4> foo2{4, 1, 2, 3};
    sort(begin(foo2), end(foo2));
}
Run Code Online (Sandbox Code Playgroud)

gcc 和 clang 都在排序上返回错误std::array-- clang 说

错误:使用未声明的标识符“排序”;你的意思是'标准::排序'?

更改以std::sort(begin(foo2), end(foo2))解决问题。

MSVC 按照编写的方式编译上面的代码。

为什么std::vector和之间的待遇不同std::array;哪个编译器是正确的?

Nat*_*ica 16

这归结为类型beginend结果以及它如何与Argument Dependent Lookup 一起使用

sort(begin(foo), end(foo));
Run Code Online (Sandbox Code Playgroud)

你得到

sort(std::vector<int>::iterator, std::vector<int>::iterator)
Run Code Online (Sandbox Code Playgroud)

并且由于std::vector<int>::iterator是其成员的stdADL的发现sortstd和调用成功。

sort(begin(foo2), end(foo2));
Run Code Online (Sandbox Code Playgroud)

你得到

sort(int*, int*)
Run Code Online (Sandbox Code Playgroud)

并且因为int*不是 的成员std,ADL 不会调查std并且您找不到std::sort.

这在 MSVC 中有效,因为

sort(begin(foo2), end(foo2));
Run Code Online (Sandbox Code Playgroud)

变成

sort(std::_Array_iterator, std::_Array_iterator)
Run Code Online (Sandbox Code Playgroud)

因为std::_Array_iteratorstdADL finds 的一部分sort

两个编译器都对这种行为是正确的。 std::vector并且std::array对迭代器使用的类型没有任何要求,除了它满足LegacyRandomAccessIterator要求,并且在 C++17 中std::array,该类型也是LiteralType,在 C++20 中它是ConstexprIterator