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


11

呼叫std::sort()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));
}

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

错误:使用未声明的标识符“ sort”;您是说'std :: sort'吗?

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

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

std::vector和之间为什么区别对待std::array; 哪个编译器正确?


sort(...-> std::sort(...。我猜想是ADL(依赖参数的查找)使您感到困惑。那或演绎指南。在任何情况下; 始终限定您调用的功能。
Jesper Juhl

3
MSVC库是否具有某种特殊性std::sort,会导致依赖参数的查找(就像您已经拥有的for std::begin和一样std::end)?
一些程序员伙计

1
@Someprogrammerdude简而言之,VC ++ stdlib中的所有容器都使用在namespace std甚至简单指针类型都可以使用的地方定义的类类型迭代器。我相信这是为了插入调试-构建检查以检测溢出和其他常见错误。
弗朗索瓦·安德里厄

Answers:


16

这归结为类型beginend结果以及如何与Argument Dependent Lookup一起工作

sort(begin(foo), end(foo));

你得到

sort(std::vector<int>::iterator, std::vector<int>::iterator)

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

sort(begin(foo2), end(foo2));

你得到

sort(int*, int*)

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

这在MSVC中有效,因为

sort(begin(foo2), end(foo2));

变成

sort(std::_Array_iterator, std::_Array_iterator)

并且因为它std::_Array_iteratorstdADL发现的一部分sort

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


1
我想这个问题是MSVC的行为是否是符合,即是否std::array迭代器必须int*,也可以是一个类类型?同样,对于std::vector迭代器是否必须是 ADL可以在其上工作的类类型还是是否也可以这样的问题int*,这也很重要。
胡桃

@walnut可以是实现所需的任何内容。可能是std::iterator,其他或只是指针。
NathanOliver

1
我也想知道为什么在这个库实现他们选择使用int*std::array,但不适合std::vector
弗朗索瓦·安德里厄

1
std::array和两者的迭代器类型std::vector是未指定的,这意味着允许实现将它们定义为原始指针(代码不会编译)或类类型包装器(仅当类类型具有std与ADL关联的命名空间时,代码才会编译)。
aschepler

1
这是一个使用别名的ADL失败的演示,这是一个使用嵌套类的ADL成功的演示。在这里和我之前的测试中,std::vector<T>::iterator都是别名。
user2357112支持Monica
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.